Quickstart
Get acp-server running, create a Covenant, and record your first contribution in under five minutes. Prerequisites: Go 1.25+ installed. No other dependencies.
1. Build & run the server
Clone and build
git clone https://github.com/ymow/acp-server
cd acp-server
go build ./...Produces two binaries: acp-server (HTTP API) and acp-mcp (MCP adapter for AI clients).
Start the server
ACP_ADDR=:8080 ACP_DB_PATH=./acp.db ./acp-serverThe server listens on :8080. SQLite DB is created automatically at./acp.db. No migrations to run.
$HOME/.acp/keys/v1.key (mode 0600) and prints its fingerprint. Back this file up — losing it permanently breaks decryption of any encrypted column. Override the location with ACP_KEY_FILE=/abs/path/master.key (the keyring lives in the sibling keys/ directory). To rotate later run acp-server rotate-key followed by acp-server reencrypt.2. Create a Covenant
Create the Covenant and get your owner token
curl -s -X POST http://localhost:8080/covenants \
-H "Content-Type: application/json" \
-d '{"name": "my-project"}' | jq .Response includes a covenant_id (e.g. cvnt_a54e1c43) and an owner_token. Save both — the owner token is shown once.
Configure contribution tiers
curl -s -X POST http://localhost:8080/covenants/$CVNT_ID/tiers \
-H "X-Owner-Token: $OWNER_TOKEN" \
-H "Content-Type: application/json" \
-d '[
{"name":"core", "multiplier": 3.0},
{"name":"feature", "multiplier": 2.0, "entry_fee_tokens": 50},
{"name":"review", "multiplier": 1.5},
{"name":"docs", "multiplier": 1.0}
]'entry_fee_tokens is optional (Phase 4.6.C, ACR-50 §7). When non-zero, an applicant joining at that tier must commit the fee from their own balance — surfaces in the audit log via the entry-fee ledger entry.Transition Covenant to OPEN
curl -s -X POST http://localhost:8080/covenants/$CVNT_ID/transition \
-H "X-Owner-Token: $OWNER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"to": "OPEN"}'Participants can now apply to join.
3. Add a participant via the ACR-50 access gate
apply before being approved, owners review applications, and entry fees (if configured) are captured. The legacy /join + approve_agent path still works for back-compat, but new integrations should use apply_to_covenant / approve_agent_access.Applicant submits an access request
curl -s -X POST http://localhost:8080/covenants/$CVNT_ID/apply \
-H "Content-Type: application/json" \
-d '{
"platform_id": "github:alice",
"tier_id": "feature",
"payment_ref": "stripe:ch_xxx",
"self_declaration": "I built the auth flow"
}' | jq .Public endpoint — applicants don't yet have a session. Returns a request_id and a 12-char platform_id_hash_prefix so the applicant can verify the server received their submission without the server re-echoing the raw platform_id (sealed at rest under ACR-700).
Owner approves the access request
curl -s -X POST http://localhost:8080/tools/approve_agent_access \
-H "X-Covenant-ID: $CVNT_ID" \
-H "X-Owner-Token: $OWNER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"params": {"request_id": "REQUEST_ID_FROM_ABOVE"}}'On approval the server creates the covenant_members row, mints a session token bound to the applicant, and (if the tier has entry_fee_tokens) records the entry-fee ledger entry. Pending requests are also surfaced via list_members for owner triage.
The applicant can poll status before approval:
curl -s -X POST http://localhost:8080/tools/get_agent_access_status \
-H "Content-Type: application/json" \
-d '{"params": {"covenant_id": "$CVNT_ID", "request_id": "REQUEST_ID"}}'Transition Covenant to ACTIVE
curl -s -X POST http://localhost:8080/covenants/$CVNT_ID/transition \
-H "X-Owner-Token: $OWNER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"to": "ACTIVE"}'Once ACTIVE, approved participants can submit passages.
Submit and approve a passage
# Participant proposes a contribution
curl -s -X POST http://localhost:8080/tools/propose_passage \
-H "X-Covenant-ID: $CVNT_ID" \
-H "X-Agent-ID: agent_alice" \
-H "X-Session-Token: $SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"params": {
"tier": "feature",
"unit_count": 200,
"description": "Implement user authentication flow"
}}' | jq .
# Owner approves (use log_id from the response)
curl -s -X POST http://localhost:8080/tools/approve_draft \
-H "X-Covenant-ID: $CVNT_ID" \
-H "X-Owner-Token: $OWNER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"params": {"log_id": "LOG_ID_FROM_ABOVE", "acceptance_ratio": 0.9}}'Tokens calculated: 200 × 2.0 × 0.9 = 360 ink
4. Settle the Covenant
Lock and generate settlement
# Lock the Covenant (no more contributions)
curl -s -X POST http://localhost:8080/covenants/$CVNT_ID/transition \
-H "X-Owner-Token: $OWNER_TOKEN" \
-d '{"to": "LOCKED"}'
# Generate settlement output
curl -s -X POST http://localhost:8080/tools/generate_settlement_output \
-H "X-Covenant-ID: $CVNT_ID" \
-H "X-Owner-Token: $OWNER_TOKEN" | jq .
# Confirm (makes it immutable)
curl -s -X POST http://localhost:8080/tools/confirm_settlement_output \
-H "X-Covenant-ID: $CVNT_ID" \
-H "X-Owner-Token: $OWNER_TOKEN"The Covenant is now in SETTLED state. The hash chain is verified. Ink totals are permanent.
GET /covenants/{id}/audit/verify