/docs/http-mode
HTTP mode — implement IICP without binary framing
HTTP mode is the mandatory transport for Phase 1–3 conformance. If your node speaks plain HTTP/JSON it can satisfy the Phase 1–3 transport requirements — no binary framing library required. Binary framing (native mode) is a Phase 4 performance upgrade, not a prerequisite for joining the mesh.
You are already in HTTP mode
5-command quickstart
These five curl calls walk through the full HTTP mode lifecycle. Replace MY_ENDPOINT with your node's public URL.
Register your node
curl -s -X POST https://iicp.network/api/v1/register \
-H "Content-Type: application/json" \
-H "X-IICP-Version: 1.9" \
-d '{
"endpoint": "https://MY_ENDPOINT",
"region": "eu-central",
"capabilities": [{
"intent": "urn:iicp:intent:llm:chat:v1",
"models": ["llama-3-8b"],
"max_tokens": 4096
}],
"limits": { "max_concurrent": 4, "tokens_per_min": 10000 }
}'Save the returned node_id and node_token — both are required for subsequent calls. The directory verifies your endpoint is reachable before accepting the registration.
Send heartbeats every 30 seconds
# Run this on a 30-second cron or in a loop
curl -s -X POST https://iicp.network/api/v1/heartbeat \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <node_token>" \
-H "X-IICP-Version: 1.9" \
-d '{
"node_id": "<node_id>",
"load": 0.4,
"queue_depth": 2,
"error_rate_1m": 0.0
}'Nodes not seen for 90 seconds are marked unavailable and disappear from discovery results. A 30-second heartbeat interval gives three missed-heartbeat tolerance before being dropped.
Expose a health endpoint
# Your node must respond to GET /iicp/health with 200 OK
# Minimal implementation (Python):
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/iicp/health':
body = json.dumps({"status":"ok","load":0.4}).encode()
self.send_response(200)
self.send_header('Content-Type','application/json')
self.send_header('X-IICP-Version','1.9')
self.end_headers()
self.wfile.write(body)
HTTPServer(('0.0.0.0', 9484), Handler).serve_forever()The directory probes GET /iicp/health during registration and periodically after. Return HTTP 200 — any body is accepted. The X-IICP-Version: 1.9 header advertises your conformance level.
Receive and serve tasks
# The IICP proxy routes tasks to your node as:
POST /v1/task
Authorization: Bearer <node_token>
Content-Type: application/json
{
"task_id": "t-abc123",
"intent": "urn:iicp:intent:llm:chat:v1",
"payload": {
"messages": [{"role": "user", "content": "Hello!"}],
"max_tokens": 512
}
}
# Your node responds:
HTTP 200 OK
Content-Type: application/json
{
"task_id": "t-abc123",
"output": { "choices": [{"message": {"role":"assistant","content":"Hi!"}}] },
"usage": { "prompt_tokens": 10, "completion_tokens": 5 }
}Authenticate the incoming node_token on every request. Return 401 if the token is missing or invalid. The adapter handles this automatically; if you are implementing a custom node, verify using constant-time comparison (bcrypt or HMAC).
Discover and verify your node is visible
# Check that your node appears in discovery results curl -s 'https://iicp.network/api/v1/discover?view=public&intent=urn:iicp:intent:llm:chat:v1' \ | python3 -m json.tool
Discovery confirmed
HTTP ↔ native message mapping
Each native binary frame type (defined in the binary framing specification) has an HTTP counterpart for the base operations. Transport-specific behavior and negotiated profiles, including task-result streaming, require their own contracts.
| Native type | Meaning | Method | Endpoint / response | Body |
|---|---|---|---|---|
| INIT (0x01) | Register node | POST | /api/v1/register | JSON or application/iicp+cbor |
| ACK (0x02) | Register response | POST | 200 response to INIT | JSON — contains node_id, node_token |
| DISCOVER (0x03) | Discover nodes | GET | /api/v1/discover?view=public&intent=<urn> | Query param: intent URN |
| CALL (0x05) | Submit task | POST | /v1/task | JSON or application/iicp+cbor |
| RESPONSE (0x06) | Task result | POST | 200 response to CALL | JSON — task output |
| FEEDBACK (0x08) | Heartbeat / liveness | POST | /api/v1/heartbeat | JSON — node_id + load metrics |
| PING (0x09) | Health check | GET | /iicp/health | No body |
| PONG (0x0A) | Health response | GET | 200 response to PING | JSON — load stats |
| OBSERVE (0x0D) | Event subscription | GET | /v1/stream (SSE) | text/event-stream |
| TELEMETRY (0x0E) | Telemetry report | POST | /v1/telemetry | JSON |
CLOSE (0x07) is implicit: any 4xx/5xx response or connection close. CONTROL (0x0B) and ADVERTISE (0x0C) map to /v1/control and /api/v1/node/{node_id} respectively — not required for Phase 1–3.
Required headers
| Header | Required on | Example value | Purpose |
|---|---|---|---|
| X-IICP-Version | All outbound requests | 1.9 | Declares conformance level — required by REACH |
| Authorization | heartbeat, task endpoints | Bearer <node_token> | Node authentication — validate on every inbound request |
| Content-Type | POST requests with body | application/json | JSON (Phase 1–3) or application/iicp+cbor (optional) |
| X-IICP-Framing | Optional | native/1 | Signal to peer that native binary framing is available |
FAQ
Do I need to implement binary framing?
No. Binary framing is a Phase 4 feature. For Phase 1–3 conformance — which covers everything from registration to task routing to heartbeats — HTTP/JSON is the MUST-implement transport. You can join the mesh, pass all REACH conformance probes, and serve real tasks entirely over HTTP.
What is the difference between HTTP mode and native mode?
The draft native mode uses a 12-byte binary frame header over TCP with CBOR-encoded payloads and integer-keyed maps defined by the binary framing specification. It adds explicit connection state, explicit CLOSE frames, fragmentation support, and lower per-message overhead. HTTP mode maps the same semantic operations to standard HTTP verbs and JSON bodies over an existing HTTP/1.1 or HTTP/2 connection. The QUIC mapping remains draft work and is not a currently supported implementation claim.
How do I know if my node is Phase 1–3 conformant?
Run the REACH conformance probe suite against your endpoint. Its active probe set covers areas such as registration format, discovery response shape, heartbeat acceptance, health endpoint availability, and telemetry authentication. Passing is project-operated evidence for the requirements covered by that run; it is not independent implementation evidence. The probe-to-requirement mapping is defined in the conformance suite.
Can I use CBOR bodies in HTTP mode?
Yes. HTTP mode optionally supports CBOR body encoding via content negotiation: send Accept: application/iicp+cbor and set Content-Type: application/iicp+cbor on your request. HTTP mode CBOR uses string-keyed maps (human-readable field names). Native framing uses integer-keyed maps. The two are semantically equivalent but structurally distinct — do not mix key styles.
What port should my node listen on?
Port 9484 is the canonical IICP port. It is in the registered range (1024–49151) per RFC 6335 and is not assigned to any other IANA-registered protocol. For Phase 1–3 you can expose port 9484 directly or terminate TLS on a standard port (443/80) and proxy to port 9484 internally. The directory performs its liveness check against whatever URL you register — the port in your endpoint field is what gets probed.
How do I implement custom intents?
Use the x.<vendor> URN prefix: urn:iicp:intent:x.acme:invoice-classify:v1. No registry approval is required. The directory accepts any x.* URN at registration time. Consumers discover your custom intent via the standard discovery endpoint — the intent string is an exact-match filter. See the intent semantics specification for the full ABNF grammar and upgrade path.
Does streaming work in HTTP mode?
Yes — via Server-Sent Events (SSE). The native OBSERVE frame (0x0D) maps to GET /v1/stream with Content-Type: text/event-stream. SSE is the Phase 1–3 streaming transport; native OBSERVE frames are Phase 4 only. The IICP adapter supports SSE streaming out of the box.
Phase 1–3 HTTP mode checklist
- ✓POST /api/v1/register — valid JSON payload, X-IICP-Version: 1.9 header
- ✓GET /iicp/health — returns HTTP 200 at all times
- ✓POST /api/v1/heartbeat — sent every ≤ 30 seconds with node_id and load
- ✓POST /v1/task — accepts task requests, verifies node_token, returns structured response
- ✓All outbound requests include Authorization: Bearer <node_token>
- ✓Endpoints follow the HTTP-to-native message mapping table
- ✓REACH conformance checks pass: iicp-reach --once (see the live stats page for current coverage)