API Reference
This section documents the Candid interfaces for all Hello World DAO canisters. Each canister exposes a set of methods that can be called from frontend applications or other canisters.
Overview
| Canister / Service | Purpose | Standards |
|---|---|---|
| user-service | User registration, profile management | Custom |
| membership | ICRC-7 Soul-Bound Token credentials | ICRC-7, ICRC-37 |
| dom-token | ICRC-1/2 token ledger with burn policies | ICRC-1, ICRC-2 |
| governance | Proposal system with vote-pass NFTs | ICRC-7 |
| treasury | Payment records, payout management | Custom |
| identity-gateway | Internet Identity integration | Custom |
| notification-service | Off-chain transactional email microservice (Resend-backed, dual-branded) | REST |
| payment-gateway | Off-chain unified payment microservice (Stripe, Stripe Connect, ICP/DOM) | REST |
| kyc | Identity verification — oracle-bridge adapter + W3C VC bridge + KycWidget | REST, ICRC-7-adjacent |
| auth-service (DEPRECATED) | Session management — replaced by PostgreSQL sessions in oracle-bridge (AUTH-001..005, 2026-04-11) | historical |
Auth migration note (2026-04-11): The
auth-servicecanister was decommissioned. Authentication now runs off-chain via oracle-bridge PostgreSQL sessions; suites validate sessions via HTTP cookies tohttps://oracle.helloworlddao.com. There are no inter-canister auth calls. See auth-service for historical reference.
Understanding Candid
Candid is the interface description language for the Internet Computer. It defines:
- Types: Records, variants, options, vectors
- Methods: Query (read-only) and update (state-changing)
- Service: The collection of methods a canister exposes
Type Conventions
// Records are like structs
type Account = record {
owner : principal;
subaccount : opt blob;
};
// Variants are like enums
type Result = variant {
Ok : nat;
Err : text;
};
// Common types
principal // IC identity
nat // Natural number (unbounded)
nat64 // 64-bit natural number
text // UTF-8 string
blob // Binary data
opt T // Optional value
vec T // Vector/arrayCalling Canister Methods
From TypeScript (Frontend)
import { Actor, HttpAgent } from '@dfinity/agent';
import { idlFactory } from './declarations/governance';
const agent = new HttpAgent({ host: 'https://ic0.app' });
const actor = Actor.createActor(idlFactory, {
agent,
canisterId: 'your-canister-id',
});
// Call a query method (fast, no consensus)
const health = await actor.health();
// Call an update method (requires consensus + active session cookie)
const result = await actor.cast_vote(
proposalId,
{ Yes: null }
);Authentication is handled out-of-band by oracle-bridge sessions (cookie-based). Inter-canister auth calls are no longer used (auth-service decommissioned 2026-04-11).
From Rust (Backend)
use ic_cdk::call;
use candid::Principal;
// Inter-canister call (example: governance → membership)
let membership_canister = Principal::from_text("tx4wx-iqaaa-aaaah-avegq-cai").unwrap();
let (result,): (Result<MemberRecord, String>,) = call(
membership_canister,
"get_member",
(caller_principal,)
).await?;From dfx CLI
# Query method
dfx canister call governance health
# Update method
dfx canister call governance cast_vote \
'(123, variant { Yes })'Common Patterns
Result Types
Most methods return a variant { Ok: T; Err: text } pattern:
const result = await actor.create_proposal(args);
if ('Ok' in result) {
console.log('Proposal ID:', result.Ok);
} else {
console.error('Error:', result.Err);
}Optional Parameters
Use empty array [] for opt types in JavaScript:
// Candid: (text, opt text) -> (Result)
await actor.some_method("required", []); // No optional value
await actor.some_method("required", ["optional-value"]); // With optionalTimestamps
All timestamps are stored as nat64 nanoseconds since Unix epoch:
// Convert JS Date to nanoseconds
const timestamp = BigInt(Date.now()) * 1_000_000n;
// Convert nanoseconds to JS Date
const date = new Date(Number(timestamp / 1_000_000n));Error Handling
Standard Error Patterns
try {
const result = await actor.cast_vote(proposalId, { Yes: null });
if ('Err' in result) {
// Handle canister-level error
switch (result.Err) {
case 'Not a member':
// Handle membership error
break;
case 'Already voted':
// Handle duplicate vote
break;
default:
// Handle unknown error
}
}
} catch (e) {
// Handle network/agent-level error
console.error('Network error:', e);
}Next Steps
- Browse individual canister APIs using the sidebar
- See Error Catalog for error codes