Quickstart
From zero to your first approved action in under 5 minutes.
Two ways to run Impri — pick one:
- Option A — Cloud: no install, a hosted key in one request. Fastest way to try it.
- Option B — Self-host:
docker compose up, your own data, still free.
Both use the exact same three calls from your agent: push an action, wait for a decision, execute and report back.
Option A — Cloud (no install)
1. Create a project and get a key
curl -s -X POST https://api.impri.dev/v1/signup \
-H "Content-Type: application/json" \
-d '{"name": "my-agent"}'Response (201 Created):
{
"key": "im_<your-key>",
"project_id": "proj_...",
"recovery_code": "...",
"note": "Store this key and recovery code securely — they will not be shown again."
}Save both — the key is shown once. (Prefer clicking through instead? Go to app.impri.dev and use the Create an API key button — same result.)
export AGENT_KEY="im_<your-key-from-the-response>"This key has full admin scope, which is fine to start. Once you're wiring up a real agent, create a narrower actions-scoped key instead — see API keys & scopes.
2. Submit an action for approval
Your agent pushes an action to the inbox. This is the single call your agent makes before doing anything consequential:
ACTION=$(curl -s -X POST https://api.impri.dev/v1/actions \
-H "Authorization: Bearer $AGENT_KEY" \
-H "Content-Type: application/json" \
-d '{
"kind": "reddit.comment",
"title": "Reply: Why is resume advice so conflicting?",
"preview": {
"format": "markdown",
"body": "The advice conflicts because different advisors optimise for different audiences — junior vs senior, IC vs management — and rarely say which."
},
"target_url": "https://reddit.com/r/cscareerquestions/comments/example",
"expires_in": 3600,
"editable": ["preview.body"]
}')
ACTION_ID=$(echo $ACTION | jq -r .id)
INBOX_URL=$(echo $ACTION | jq -r .inbox_url)
echo "Review it at: $INBOX_URL"3. Approve in the web inbox
Open the inbox_url printed above (or go to app.impri.dev and click Inbox). You'll see the pending action as a card with the markdown preview. Tap Approve (or Reject).
If you configured editable: ["preview.body"], you can also edit the reply text before approving — the agent receives the final, human-edited version.
4. Agent picks up the decision via polling
Poll GET /v1/actions/:id until status is no longer pending:
curl -s https://api.impri.dev/v1/actions/$ACTION_ID \
-H "Authorization: Bearer $AGENT_KEY" | jq '{status, decision}'Response after approval:
{
"status": "approved",
"decision": {
"verdict": "approve",
"decided_at": 1719996800,
"channel": "web",
"final_preview": {
"format": "markdown",
"body": "The advice conflicts because different advisors optimise for different audiences..."
}
}
}If the reviewer edited the body, final_preview contains the edited version and diff is present. Always use final_preview as the content to send — never the original.
5. Execute and report back
Execute the action with the approved content, then close the loop by reporting the result:
# After successful execution
curl -s -X POST https://api.impri.dev/v1/actions/$ACTION_ID/result \
-H "Authorization: Bearer $AGENT_KEY" \
-H "Content-Type: application/json" \
-d '{"status": "executed"}'
# Or if execution failed
curl -s -X POST https://api.impri.dev/v1/actions/$ACTION_ID/result \
-H "Authorization: Bearer $AGENT_KEY" \
-H "Content-Type: application/json" \
-d '{"status": "execute_failed", "detail": "Reddit API returned 403"}'The action lifecycle is now complete: pending → approved → executed. That's the whole loop — everything past this point is optional depth (webhooks instead of polling, watchers, notification channels).
Prefer MCP? (Claude Code, Codex CLI, Cursor, Windsurf, any MCP client)
Skip the raw HTTP calls above — the Impri MCP server wraps the same three calls into tool calls your agent can use directly. The web inbox's Connect an agent panel shows the same commands below with your real key already filled in.
Claude Code:
claude mcp add impri \
-e IMPRI_API_KEY=im_<your-agent-key> \
-e IMPRI_BASE_URL=https://api.impri.dev \
-- npx -y @impri/mcpCodex CLI:
codex mcp add impri \
--env IMPRI_API_KEY=im_<your-agent-key> \
--env IMPRI_BASE_URL=https://api.impri.dev \
-- npx -y @impri/mcpCursor (~/.cursor/mcp.json or .cursor/mcp.json in your project), Windsurf (~/.codeium/windsurf/mcp_config.json), Claude Desktop, or any other MCP client — same JSON shape:
{
"mcpServers": {
"impri": {
"command": "npx",
"args": ["-y", "@impri/mcp"],
"env": {
"IMPRI_API_KEY": "im_<your-agent-key>",
"IMPRI_BASE_URL": "https://api.impri.dev"
}
}
}
}Self-hosting? Drop the IMPRI_BASE_URL line — the MCP server already defaults to http://localhost:8484.
| Tool | What it does |
|---|---|
impri_push_action |
Submit an action for human approval |
impri_await_decision |
Long-poll until a decision arrives (or timeout) |
impri_report_result |
Report execution outcome after approval |
impri_inbox_status |
Check how many actions are pending |
impri_push_action(kind="reddit.comment", title="Reply: ...", preview={...}, editable=["preview.body"])
→ { action_id: "act_abc123", status: "pending", inbox_url: "..." }
impri_await_decision(action_id="act_abc123", timeout_s=600)
→ { status: "approved", preview: { body: "..." }, edited_by_human: true }
impri_report_result(action_id="act_abc123", status="executed")Option B — Self-host (Docker)
Same three calls, running entirely on your own machine — no cloud account, no telemetry.
Prerequisites: Docker and Docker Compose, curl.
1. Start Impri
git clone https://gitlab.com/sekera.radim/impri.git
cd impri
# Set a strong webhook secret before starting
export WEBHOOK_SECRET=$(openssl rand -hex 32)
docker compose up -dThe server starts on port 8484 (API) and the web inbox on port 8080.
On the very first start, a bootstrap admin key is printed to the server log — grab it now, it's shown once and hashed in the database from then on:
docker compose logs server | grep "Admin API Key"export ADMIN_KEY="im_<your-key-from-the-log>"2. Create an API key for your agent
The bootstrap key has admin scope. Create a dedicated key with actions scope for your agent so you can rotate it independently:
curl -s -X POST http://localhost:8484/v1/keys \
-H "Authorization: Bearer $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "my-agent", "scopes": ["actions"]}' | tee /dev/stderr | jq .keyexport AGENT_KEY="im_<agent-key>"3–6. Push, approve, poll, execute
Same as the cloud steps above, just swap https://api.impri.dev for http://localhost:8484 and https://app.impri.dev for http://localhost:8080:
# 3. Push
curl -s -X POST http://localhost:8484/v1/actions \
-H "Authorization: Bearer $AGENT_KEY" \
-H "Content-Type: application/json" \
-d '{
"kind": "reddit.comment",
"title": "Reply: Why is resume advice so conflicting?",
"preview": { "format": "markdown", "body": "The advice conflicts because different advisors optimise for different audiences..." },
"target_url": "https://reddit.com/r/cscareerquestions/comments/example",
"expires_in": 3600,
"editable": ["preview.body"]
}'
# → { "id": "act_abc123", "status": "pending", "inbox_url": "http://localhost:8080/inbox/act_abc123", ... }
# 4. Approve at the inbox_url above, then poll
curl -s http://localhost:8484/v1/actions/act_abc123 \
-H "Authorization: Bearer $AGENT_KEY" | jq '{status, decision}'
# 5. Execute with decision.final_preview, then report
curl -s -X POST http://localhost:8484/v1/actions/act_abc123/result \
-H "Authorization: Bearer $AGENT_KEY" \
-H "Content-Type: application/json" \
-d '{"status": "executed"}'Via MCP: same config as Option A, just point it at your local server:
export IMPRI_API_KEY="$AGENT_KEY"
export IMPRI_BASE_URL="http://localhost:8484"
npx @impri/mcpWhat's next
- Webhook delivery instead of polling: see webhooks.md
- Watchers (monitor RSS, Reddit, URL changes): REST API via
POST /v1/watchers; see SPEC.md for the schema - Self-hosting configuration (SMTP, ntfy, backups): see self-hosting.md
- The full pattern and its guarantees (why this actually gates execution, and what it doesn't cover): see How to add human approval to an AI agent