Public API

The IMAA REST API mirrors everything you can do in the dashboard: manage contracts, monitor targets, alert rules, channels, and read alert history. It is a Pro and above feature.

Get an API key

Go to Settings → API Keys and click + Create key. Pick a scope (read-only vs read-write), optional restrictions (specific contracts or chains), and optional expiry. Full walkthrough in Managing API Keys.

The full key is shown once at creation time and never again. Store it in your secret manager immediately. After that, the dashboard only shows the prefix (imaa_xxxx...) for identification. Lost keys can't be recovered — revoke and rotate.

Keys are stored as SHA-256 hashes at rest. The plaintext leaves our servers exactly once, in the response to the create call.

Authentication

Send the key as a bearer token on every request:

Authorization: Bearer imaa_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Examples

List your contracts:

curl https://imaa-api.w3i.io/api/v1/contracts \
  -H "Authorization: Bearer $IMAA_API_KEY"

Create a contract (chain name is the string key from the chains registry):

curl https://imaa-api.w3i.io/api/v1/contracts \
  -H "Authorization: Bearer $IMAA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "chain": "base",
    "address": "0x4200000000000000000000000000000000000006",
    "label": "WETH on Base",
    "selected_targets": [
      {"target_type": "tx_rate"}
    ]
  }'

List recent alert events across all rules:

curl "https://imaa-api.w3i.io/api/v1/alerts/history?limit=50" \
  -H "Authorization: Bearer $IMAA_API_KEY"

Full schema, every endpoint, every field — see the live OpenAPI reference at imaa-api.w3i.io/docs.

Wallet discovery

Bulk-import contracts connected to a wallet. See the full user guide for how this works. Pro+ only.

Start a discovery for an Ethereum wallet:

curl https://imaa-api.w3i.io/api/v1/wallet-discoveries \
  -H "Authorization: Bearer $IMAA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "wallet_address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
    "chain_ids": [1]
  }'

Response is 202 Accepted with a status of pending (or completed if results are cached). Poll GET /wallet-discoveries/{id} every 2 seconds until status is completed, partial, or failed:

curl https://imaa-api.w3i.io/api/v1/wallet-discoveries/$ID \
  -H "Authorization: Bearer $IMAA_API_KEY"

Then import selected results — up to 100 addresses per request. Setting enable_suggested_targets: true attaches category-appropriate monitor targets so each contract ships in monitoring status rather than pending:

curl https://imaa-api.w3i.io/api/v1/wallet-discoveries/$ID/import \
  -H "Authorization: Bearer $IMAA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "addresses": [
      { "address": "0xabc...", "chain_id": 1, "enable_suggested_targets": true },
      { "address": "0xdef...", "chain_id": 1 }
    ]
  }'

Response includes imported / skipped / failed counters plus per-address error details in errors. Contracts already in your org are skipped (not re-imported).

Scoped keys

Keys can be minted read-only, or restricted to specific contracts or chains. Full walkthrough in Managing API Keys.

Mint a read-only key scoped to two specific contracts on Ethereum, expiring in 90 days:

curl https://imaa-api.w3i.io/api/v1/api-keys \
  -H "Authorization: Bearer $IMAA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "analytics-readonly",
    "scope": "read_only",
    "contract_scope": [
      "3f9e4a2b-1c6d-4e7f-9a0b-2c8d4e5f6a7b",
      "5a8b6c7d-9e0f-4a1b-8c2d-3e4f5a6b7c8d"
    ],
    "chain_scope": [1],
    "expires_at": "2026-07-22T00:00:00Z"
  }'

The response contains the plaintext key once — copy it immediately.

Handling auth responses

StatusWhyAction
401 UnauthorizedKey missing, invalid, revoked, or past its expiryCheck Authorization header is set. Then check the dashboard — the key may have been revoked or expired.
403 ForbiddenScope violation: read-only key doing a mutation, or scoped key touching an out-of-scope contract/chainUse a wider key. These denials are logged to the admin audit log as api_key.scope_denied.
429 Too Many RequestsPer-key rate limit exceededBack off using the Retry-After header, or upgrade for a higher limit.

Rate limits

Per-key, sliding window:

TierRequests / minute
Free30
Pro300
Team1,200
Enterprise6,000

Over-limit responses return 429 Too Many Requests with a Retry-After header. Back off and retry.