Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
357 changes: 346 additions & 11 deletions docs/reference/ic-interface-spec.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,355 @@
---
title: "IC Interface Specification"
description: "Summary and links to the IC interface specification: System API, HTTP interface, certified data"
description: "Overview of the Internet Computer interface specification: System API, HTTP interface, certified data, and management canister"
sidebar:
order: 9
---

TODO: Write content for this page.
The IC interface specification is the authoritative formal description of the Internet Computer's external interfaces. It describes what the IC guarantees to canister developers, agents, tooling authors, and anyone building on the protocol.

<!-- Content Brief -->
Summary page for the IC interface specification. Provide a structured overview of the spec sections: System API (canister imports), HTTP interface (ingress messages, read state), certified data, canister lifecycle, and management canister. Link to the full specification for each section. This page serves as a navigation aid, not a duplication of the spec.
This page gives a structured overview of the spec's main sections to help you find what you need. The spec itself is precise and technically dense — it is the ground truth for behavior, error handling, and protocol invariants.

<!-- Source Material -->
- Portal: references/ic-interface-spec.mdx
- Full spec: https://internetcomputer.org/docs/references/ic-interface-spec
The full specification is available as a reference document for tooling authors, CDK implementers, and protocol contributors.

<!-- Cross-Links -->
- reference/management-canister -- management canister subset
- reference/candid-spec -- encoding used by the interface
- reference/http-gateway-spec -- HTTP gateway protocol
## Who should read the IC interface spec

The IC interface spec is aimed at:

- **Tooling and agent authors** — those implementing agents, canister development kits, emulators, or other tooling that interacts directly with the IC at the protocol level.
- **Security researchers** — those performing detailed security analysis of IC behavior.
- **Protocol contributors** — those working on the IC implementation itself.

Most canister developers interact with the IC through CDKs (Motoko, Rust CDK) and the icp-cli toolchain. For practical development guides, see the [guides section](../guides/index.md) and the [management canister reference](management-canister.md).

## Pervasive concepts

Several concepts apply across all interfaces described in the spec.

### Principals

Principals are the generic identifier type for canisters, users, and other entities on the IC. They are binary blobs between 0 and 29 bytes long. The spec defines five classes of principal:

| Class | Form | Used for |
|---|---|---|
| Opaque | Generated by the IC | Canister IDs assigned by the IC |
| Self-authenticating | `SHA-224(public_key) · 0x02` | External user identities |
| Derived | Hash of registering principal and derivation nonce | May be used internally; not currently used in the public spec |
| Anonymous | `0x04` | Unsigned calls |
| Reserved | `blob · 0x7f` | Application-defined identifiers |

The **textual representation** of a principal is `Grouped(Base32(CRC32(blob) · blob))` — groups of 5 characters separated by dashes, in lowercase. For example, the management canister ID is `aaaaa-aa`.

### Canister lifecycle

A canister has the following state:

- A canister ID (principal)
- A list of controllers (up to 10 principals)
- A cycle balance and a reserved cycles balance
- A status: `running`, `stopping`, or `stopped`

A canister is either **empty** (no installed code) or **non-empty** (has a Wasm module, heap memory, stable memory, and globals). Canisters start empty after creation. An empty canister that receives a response drops the response and credits the cycles back to its balance.

When both the main and reserved cycle balances reach zero, the canister is **deallocated**: its code and memory are freed, but its ID, cycle balances, controllers, version, and change count are preserved for at least 10 years.

For lifecycle management from a developer perspective, see the [canister lifecycle guide](../guides/canister-management/lifecycle.md).

### Canister status

| Status | Behavior |
|---|---|
| `running` | Calls are processed normally |
| `stopping` | Incoming calls are rejected with `CANISTER_ERROR`; responses continue to be processed |
| `stopped` | Incoming calls are rejected; no outstanding responses remain |

Calls to the management canister (`aaaaa-aa`) are always processed regardless of the managed canister's status.

### Signatures

The IC supports multiple signature schemes for authentication:

| Scheme | OID / Description |
|---|---|
| Ed25519 | Edwards-curve signature |
| ECDSA on secp256k1 | Used by Bitcoin-compatible keys |
| ECDSA on secp256r1 | P-256, used by passkeys and WebAuthn |
| RSA PKCS#1 v1.5 with SHA-256 | For legacy key types |
| Canister signatures | IC-specific delegated signatures from a canister |

The spec also defines a **delegation chain** mechanism: a key may delegate signing authority to another key with optional restrictions on target canisters and expiry times.

## System state tree

The IC maintains a **system state tree** — a Merkle tree whose root hash is published in every certified response. Clients can request a partial tree (a **certificate**) and verify that any value in it was produced by the IC.

Key subtrees of the state tree:

| Path | Content |
|---|---|
| `/time` | Current IC time in nanoseconds since Unix epoch |
| `/api_boundary_nodes/<node_id>/...` | API boundary node information (domain, IPv4/IPv6) |
| `/subnet/<subnet_id>/...` | Subnet public key, canister ID ranges, node IDs |
| `/request_status/<request_id>/...` | Status of a submitted request (received, processing, replied, rejected, done) |
| `/canister/<canister_id>/certified_data` | 32-byte blob set by the canister |
| `/canister/<canister_id>/module_hash` | SHA-256 of the installed Wasm module |
| `/canister/<canister_id>/controllers` | CBOR-encoded list of controller principals |

The **certified data** subtree is used by canisters to publish verifiable values in query responses. See the [certified variables guide](../guides/backends/certified-variables.md) for a practical walkthrough.

The **request status** subtree lets clients verify the outcome of update calls. Statuses progress through: `received` → `processing` → `replied` or `rejected` → `done`.

## HTTPS interface

External users interact with the IC by sending HTTPS requests to a **boundary node**. The boundary node routes requests to the appropriate subnet replica.

### Endpoints

All endpoints accept and return CBOR-encoded messages.

| Endpoint | Method | Description |
|---|---|---|
| `/api/v2/canister/<effective_canister_id>/call` | POST | Submit an update call (synchronous response is provisional ACK) |
| `/api/v2/canister/<effective_canister_id>/read_state` | POST | Read certified state from the state tree |
| `/api/v2/canister/<effective_canister_id>/query` | POST | Execute a query call (non-replicated, fast) |
| `/api/v2/subnet/<subnet_id>/read_state` | POST | Read subnet-level state |
| `/api/v2/status` | GET | IC status and versioning information |

There is also an asynchronous call endpoint at `/api/v3/canister/<effective_canister_id>/call` that returns a signed acknowledgement and the request ID without waiting for the call to reach consensus.

### Request structure

All update, read state, and query requests share a common envelope structure:

```
{
"sender_pubkey": <public key bytes>,
"sender_sig": <signature bytes>,
"content": {
"request_type": "call" | "read_state" | "query",
"sender": <principal>,
"nonce": <optional random bytes>,
"ingress_expiry": <nanoseconds since Unix epoch>,
...request-specific fields...
}
}
```

Requests are authenticated by signing the request content. Anonymous requests use `sender = 0x04` and omit the key and signature fields.

### Ingress messages

An **ingress message** is a call submitted by an external user. The `ingress_expiry` field sets a deadline (expressed in nanoseconds since the Unix epoch) after which the IC will not execute the call. The IC may refuse requests with an expiry too far in the future; the exact window is implementation-defined (the IC mainnet currently rejects requests with an ingress expiry more than 5 minutes in the future). Once submitted, the caller polls `/read_state` using the request ID to determine the outcome.

### Query calls

Query calls are executed by a single replica (non-replicated). They are fast but do not produce certified results — a malicious replica could return incorrect data. For verified query responses, use **certified data** in combination with a `read_state` request to verify the certificate.

### Effective canister ID

Requests must include an **effective canister ID** in the URL path. For most calls this is the target canister. For calls to the management canister that create a new canister, the effective canister ID must be the subnet ID. For other management canister calls, it is the target canister ID.

### Authentication

Requests are authenticated using the sender's key and a signature over the request content hash. The spec defines **representation-independent hashing** — a deterministic algorithm for hashing structured request data — and **request IDs** — the hash used to identify a submitted request when polling for status.

### Reject codes

When a call is rejected, the response includes a reject code:

| Code | Symbolic name | Meaning |
|---|---|---|
| 1 | `SYS_FATAL` | Fatal system error; retry will not help |
| 2 | `SYS_TRANSIENT` | Transient system error; retry may succeed |
| 3 | `DESTINATION_INVALID` | Target canister does not exist or is not a valid destination |
| 4 | `CANISTER_REJECT` | Canister explicitly rejected the call with `ic0.msg_reject` |
| 5 | `CANISTER_ERROR` | Canister trapped or the IC rejected due to canister state |

## Canister module format

A canister module is a **WebAssembly binary** (raw `.wasm` or gzip-compressed) that exports specific entry points and imports System API functions. The IC validates the module at install time:

- The module must be a valid WebAssembly binary.
- Any System API imports must match the exact signatures defined in the spec.
- The module may declare at most one memory.
- The module must not use features that the IC's Wasm engine does not support.

## Canister interface (System API)

The System API is the set of WebAssembly **import functions** provided by the IC to canister code. Canisters import these under the module name `"ic0"`.

### Entry points

The IC invokes canisters through well-defined **entry points** — exported WebAssembly functions with specific names:

| Entry point | When invoked |
|---|---|
| `canister_init` | After code installation (`install` mode) |
| `canister_post_upgrade` | After code installation (`upgrade` mode) |
| `canister_pre_upgrade` | Before code replacement (during upgrade) |
| `canister_inspect_message` | Before accepting an ingress message (update calls only) |
| `canister_heartbeat` | Periodically by the IC (replicated) |
| `canister_global_timer` | When the canister's global timer fires |
| `canister_on_low_wasm_memory` | When Wasm heap approaches the configured threshold |
| `canister_update <name>` | Update method call |
| `canister_query <name>` | Query method call |
| `canister_composite_query <name>` | Composite query method call |

Entry points run in either **replicated** mode (all replicas execute and must agree) or **non-replicated** mode (single replica). Update calls and heartbeats run replicated. Query calls and composite queries run non-replicated.

### Replicated vs. non-replicated execution

| Mode | Guarantees | Restrictions |
|---|---|---|
| Replicated | State mutations are committed; results are consensus-verified | Higher latency |
| Non-replicated | Fast; single-replica execution | State mutations are discarded; cannot make inter-canister calls (except composite query → composite query) |

### System API import categories

The System API is organized into functional groups:

**Call context** — reading the current call's arguments, sender, method name, cycles attached:
- `ic0.msg_arg_data_copy` / `ic0.msg_arg_data_size`
- `ic0.msg_caller_copy` / `ic0.msg_caller_size`
- `ic0.msg_method_name_copy` / `ic0.msg_method_name_size`
- `ic0.msg_cycles_available128` / `ic0.msg_cycles_refunded128`
- `ic0.msg_reject_code` / `ic0.msg_reject_msg_copy`

**Responding** — sending a reply or reject from the current call:
- `ic0.msg_reply_data_append` / `ic0.msg_reply`
- `ic0.msg_reject`

**Inter-canister calls** — initiating calls to other canisters:
- `ic0.call_new` / `ic0.call_on_cleanup`
- `ic0.call_data_append` / `ic0.call_cycles_add128`
- `ic0.call_perform`

**Canister identity** — reading own canister ID, version, and status:
- `ic0.canister_self_copy` / `ic0.canister_self_size`
- `ic0.canister_version`
- `ic0.canister_status`

**Cycles** — managing cycle balances:
- `ic0.canister_cycle_balance128`
- `ic0.msg_cycles_accept128`
- `ic0.cycles_burn128`

**Stable memory** — 64-bit stable memory read/write:
- `ic0.stable64_read` / `ic0.stable64_write`
- `ic0.stable64_size` / `ic0.stable64_grow`

**Time and randomness** — reading the current time and accessing a per-message random seed:
- `ic0.time`
- `ic0.performance_counter`
- `ic0.is_controller`
- `ic0.in_replicated_execution`

**Certified data** — writing the 32-byte certified data blob:
- `ic0.certified_data_set`

**Logging** — emitting debug messages and printing:
- `ic0.debug_print`
- `ic0.trap`

**Environment variables** — reading key-value pairs set in canister settings:
- `ic0.env_var_copy` / `ic0.env_var_size`

For CDK-level abstractions over these imports, see the [Rust CDK docs](https://docs.rs/ic-cdk/latest/ic_cdk/) and the [Motoko core library](https://mops.one/core/docs).

### Ingress message inspection

Before executing an ingress update call, the IC calls `canister_inspect_message` if it is exported. The entry point can accept or reject the call by calling `ic0.accept_message` or trapping. If `canister_inspect_message` is not exported, all ingress calls are accepted.

`canister_inspect_message` runs non-replicated — it is a filter, not a security boundary for on-chain state. Any secrets or state-dependent authorization must be enforced inside the actual update method.

## The IC management canister

The **management canister** (`aaaaa-aa`) is a virtual canister that provides access to IC platform features. It is not a real Wasm canister — it is implemented directly in the IC protocol.

The spec defines the full interface of the management canister. For a practical API reference with all methods and their parameters, see the [management canister reference](management-canister.md).

Key method groups:

| Category | Methods |
|---|---|
| Canister lifecycle | `create_canister`, `install_code`, `install_chunked_code`, `uninstall_code`, `start_canister`, `stop_canister`, `delete_canister`, `update_settings` |
| Canister inspection | `canister_status`, `canister_info`, `canister_metadata` |
| Chunk store | `upload_chunk`, `clear_chunk_store`, `stored_chunks` |
| Snapshots | `take_canister_snapshot`, `load_canister_snapshot`, `list_canister_snapshots`, `delete_canister_snapshot`, `read_canister_snapshot_metadata`, `read_canister_snapshot_data`, `upload_canister_snapshot_metadata`, `upload_canister_snapshot_data` |
| Chain-key signing | `ecdsa_public_key`, `sign_with_ecdsa`, `schnorr_public_key`, `sign_with_schnorr`, `vetkd_public_key`, `vetkd_derive_key` |
| HTTPS outcalls | `http_request` |
| Randomness | `raw_rand` |
| Cycles | `deposit_cycles` |
| Node metrics | `node_metrics_history`, `subnet_info` |
| Logs | `fetch_canister_logs` |

## Certified data and certification

Canister code can write a **32-byte certified data blob** using `ic0.certified_data_set`. This blob is included in the IC's system state tree at `/canister/<canister_id>/certified_data`, and the tree root hash is signed by the subnet in every certified response.

A client that wants to verify a query response can:
1. Request the certificate via `read_state`
2. Verify the subnet signature on the tree root
3. Walk the tree to retrieve the `certified_data` value
4. Verify that the data matches a commitment included in the query response

This pattern allows query responses to carry verifiable commitments without requiring update calls. See the [certified variables guide](../guides/backends/certified-variables.md) for a practical implementation.

## Certificate structure

The spec defines the structure of **certificates** — data structures that prove a value was part of the IC's state tree at a given time. A certificate contains:

- A **tree** — a partial Merkle tree with the relevant path and leaf values
- A **signature** — a threshold BLS signature from the subnet over the tree root
- An optional **delegation chain** — proving the signing subnet was authorized by the NNS root key

The root key of the IC is published in the status endpoint (`/api/v2/status`) and known to clients that want to verify certificates independently.

For developer-facing information on response certification, see [certified variables](../guides/backends/certified-variables.md).

## Bitcoin API

The spec includes a dedicated **Bitcoin API** section covering integration with the Bitcoin network:

| Method | Description |
|---|---|
| `bitcoin_get_utxos` | Query unspent transaction outputs for a Bitcoin address |
| `bitcoin_get_balance` | Get the balance of a Bitcoin address |
| `bitcoin_send_transaction` | Broadcast a signed Bitcoin transaction |
| `bitcoin_get_current_fee_percentiles` | Get current fee percentile data |
| `bitcoin_get_block_headers` | Read Bitcoin block headers |

These are management canister methods used for the IC's native Bitcoin integration. For usage guidance, see the [Bitcoin integration guide](../guides/chain-fusion/bitcoin.md).

## HTTP Gateway protocol

The **HTTP Gateway protocol** describes how IC boundary nodes translate HTTP requests from browsers into canister calls, and how they verify and serve certified HTTP responses.

The HTTP Gateway spec is a separate specification referenced from the main IC interface spec. For an overview, see the [HTTP Gateway spec page](http-gateway-spec.md).

## Abstract behavior

The final section of the IC interface spec provides a formal pseudocode description of the IC's abstract state machine. It defines:

- The abstract state (canister queues, message routing, consensus inputs)
- State transition rules for every type of request and system event
- Ordering guarantees and synchronicity properties

This section is aimed at protocol implementers and formal verification. It is not required reading for canister developers.

## Relationship to other specifications

| Topic | Where it lives |
|---|---|
| Management canister API reference | [management-canister.md](management-canister.md) |
| Candid type system and encoding | [candid-spec.md](candid-spec.md) |
| HTTP Gateway protocol | [http-gateway-spec.md](http-gateway-spec.md) |
| Canister-level certified data | [certified variables guide](../guides/backends/certified-variables.md) |
| Canister lifecycle operations | [lifecycle guide](../guides/canister-management/lifecycle.md) |

## Next steps

- Read the [management canister reference](management-canister.md) for a developer-friendly API reference.
- See the [certified variables guide](../guides/backends/certified-variables.md) to learn how to build verifiable query responses.
- Read the [Candid specification](candid-spec.md) for the interface description language used to encode method arguments and results.

<!-- Upstream: informed by dfinity/portal — docs/references/ic-interface-spec.md -->
Loading