Quickstart

From zero to your first approved action in under 5 minutes.

Two ways to run Impri — pick one:

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

bash
curl -s -X POST https://api.impri.dev/v1/signup \
  -H "Content-Type: application/json" \
  -d '{"name": "my-agent"}'

Response (201 Created):

json
{
  "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.)

bash
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:

bash
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:

bash
curl -s https://api.impri.dev/v1/actions/$ACTION_ID \
  -H "Authorization: Bearer $AGENT_KEY" | jq '{status, decision}'

Response after approval:

json
{
  "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:

bash
# 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:

bash
claude mcp add impri \
  -e IMPRI_API_KEY=im_<your-agent-key> \
  -e IMPRI_BASE_URL=https://api.impri.dev \
  -- npx -y @impri/mcp

Codex CLI:

bash
codex mcp add impri \
  --env IMPRI_API_KEY=im_<your-agent-key> \
  --env IMPRI_BASE_URL=https://api.impri.dev \
  -- npx -y @impri/mcp

Cursor (~/.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:

json
{
  "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

bash
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 -d

The 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:

bash
docker compose logs server | grep "Admin API Key"
bash
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:

bash
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 .key
bash
export 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:

bash
# 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:

bash
export IMPRI_API_KEY="$AGENT_KEY"
export IMPRI_BASE_URL="http://localhost:8484"
npx @impri/mcp

What's next