ICN Gateway API (OpenAPI directory)

The ICN Gateway provides a REST and WebSocket API for cooperative applications.

Quick Links

Base URL

http://localhost:8080/v1

Authentication

The Gateway uses DID-based challenge-response authentication with JWT tokens.

Getting a Token

# 1. Request challenge
curl -X POST http://localhost:8080/v1/auth/challenge \
  -H "Content-Type: application/json" \
  -d '{"did": "did:icn:YOUR_DID"}'

# Response: {"challenge": "abc123...", "expires_at": "..."}

# 2. Sign and verify (using icnctl)
TOKEN=$(icnctl auth token --coop my-coop)

# 3. Use token
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:8080/v1/coops/my-coop

Endpoints Overview

Health

Method Endpoint Description
GET /v1/health Service health check

Authentication

Method Endpoint Description
POST /v1/auth/challenge Request auth challenge
POST /v1/auth/verify Verify signature, get JWT

Cooperatives

Method Endpoint Scope Required Description
GET /v1/coops coop:read List cooperatives
POST /v1/coops coop:write Create cooperative
GET /v1/coops/{id} coop:read Get cooperative
PUT /v1/coops/{id} coop:write Update cooperative
DELETE /v1/coops/{id} coop:admin Delete cooperative
GET /v1/coops/{id}/members coop:read List members
POST /v1/coops/{id}/members coop:admin Add member
PUT /v1/coops/{id}/members/{did} coop:admin Update member role
DELETE /v1/coops/{id}/members/{did} coop:admin Remove member

Ledger

Method Endpoint Scope Required Description
GET /v1/ledger/{coop}/position/{did} ledger:read Get net position (derived from signed receipts)
POST /v1/ledger/{coop}/settle ledger:write Record a settlement (transfer of obligations)
POST /v1/ledger/{coop}/settle/convert ledger:write Record a cross-unit settlement
GET /v1/ledger/{coop}/history ledger:read State-change journal history
GET /v1/ledger/{coop}/entries/by-decision ledger:read Journal entries by governance decision

Legacy vocabulary (deprecated — not served)

Earlier drafts of this doc used payment-rail terms. Per ADR-0006 (renamed in PR #1315) these were replaced with ICN-native primitives. The old names are not served by the gateway and return 404:

Deprecated (removed) Canonical ICN primitive
POST /v1/ledger/{coop}/payment POST /v1/ledger/{coop}/settle — settlement of obligations
GET /v1/ledger/{coop}/balance/{did} GET /v1/ledger/{coop}/position/{did} — net position
currency request field unit request field
PaymentCreated event SettlementCreated event

Governance

Method Endpoint Scope Required Description
GET /v1/gov/domains gov:read List domains
POST /v1/gov/domains gov:write Create domain
GET /v1/gov/domains/{id} gov:read Get domain
GET /v1/gov/domains/{id}/proposals gov:read List proposals
POST /v1/gov/domains/{id}/proposals gov:write Create proposal
GET /v1/gov/proposals/{id} gov:read Get proposal
POST /v1/gov/proposals/{id}/open gov:write Open voting
POST /v1/gov/proposals/{id}/close gov:write Close & tally
POST /v1/gov/proposals/{id}/vote gov:write Cast vote
GET /v1/gov/proposals/{id}/vote gov:read Get vote tally

WebSocket

Endpoint Description
GET /v1/ws/{coop_id} Real-time event stream

Common Examples

Create a Cooperative

curl -X POST http://localhost:8080/v1/coops \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "food-coop",
    "name": "Downtown Food Cooperative",
    "description": "A community food buying club"
  }'

Record a Settlement

curl -X POST http://localhost:8080/v1/ledger/food-coop/settle \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "did:icn:sender",
    "to": "did:icn:recipient",
    "amount": 2,
    "unit": "hours",
    "memo": "Garden help - 2 hours weeding"
  }'

Create a Governance Proposal

curl -X POST http://localhost:8080/v1/gov/domains/coop:food/proposals \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Approve new supplier contract",
    "description": "Vote to approve the contract with Green Valley Farms",
    "kind": "text"
  }'

Cast a Vote

curl -X POST http://localhost:8080/v1/gov/proposals/$PROPOSAL_ID/vote \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"choice": "for"}'

Connect to WebSocket

const ws = new WebSocket('ws://localhost:8080/v1/ws/food-coop');

ws.onopen = () => {
  ws.send(JSON.stringify({ type: 'Auth', token: TOKEN }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  if (msg.type === 'AuthOk') {
    console.log('Authenticated as', msg.did);
  } else if (msg.type === 'Event') {
    console.log('Event:', msg);
  }
};

Rate Limiting

All authenticated endpoints are rate-limited per DID:

  • Burst capacity: 100 requests
  • Refill rate: 10 tokens/second

When rate limited, the API returns HTTP 429 with a Retry-After header.

Error Responses

All errors return JSON with error and message fields:

{
  "error": "Forbidden",
  "message": "Missing required scope: ledger:write"
}
Status Meaning
400 Bad Request - Invalid parameters
401 Unauthorized - Missing/invalid token
403 Forbidden - Insufficient permissions
404 Not Found - Resource doesn't exist
409 Conflict - Resource already exists
422 Unprocessable - Business logic error (e.g., settlement exceeds the account's credit limit)
429 Too Many Requests - Rate limited

WebSocket Events

After authentication, you'll receive events as they occur:

Event Type Description
SettlementCreated New settlement recorded in the journal
MemberAdded Member joined cooperative
MemberRemoved Member left cooperative
RoleUpdated Member's role changed
SettingsUpdated Cooperative settings changed
GovernanceDomainCreated New governance domain
GovernanceProposalCreated New proposal
GovernanceProposalOpened Proposal opened for voting
GovernanceProposalClosed Proposal closed with outcome
GovernanceVoteCast Vote cast on proposal

Running Examples

Run the example script to test all API endpoints:

# Run health check only (no token needed)
./docs/api/examples.sh

# Run all examples with authentication
export TOKEN=$(icnctl auth token --coop my-coop)
./docs/api/examples.sh

The script demonstrates:

  • Health checks
  • Cooperative management
  • Member management
  • Ledger operations (position, settlement)
  • Governance (domains, proposals, voting)

Viewing the OpenAPI Spec

You can view the interactive API documentation using:

Swagger UI

docker run -p 8081:8080 -e SWAGGER_JSON=/spec/openapi.yaml \
  -v $(pwd)/docs/api:/spec swaggerapi/swagger-ui

Then open http://localhost:8081

Redoc

docker run -p 8081:80 -e SPEC_URL=/spec/openapi.yaml \
  -v $(pwd)/docs/api:/usr/share/nginx/html/spec redocly/redoc

Then open http://localhost:8081

SDK Support

  • TypeScript: See sdk/typescript/ for the official TypeScript client
  • Python: Coming soon
  • Rust: Use icn-gateway crate directly

License

MIT OR Apache-2.0