Overview
The API has three core resources. A mandate is your organization's direction, compiled into something a model can deliver. A Familiar is an agent paired with one participant. Alignment is what you read back.
Every account starts in a sandbox tenant with synthetic participants. Production keys are issued during onboarding, after your first mandate has run in observation mode.
Quickstart
- Create a key. In the admin console, go to Settings → API keys. Keep it on your server.
- Publish a mandate in observation mode. Nothing reaches participants yet. You will see the interventions Murmur would have delivered.
- Pair a Familiar. Choose a participant and a connector. Pairings start in review.
- Switch delivery on. When an administrator approves, set
deliveryto"deliver". Most teams report 0.9 alignment within 48 hours. Telemetry catches up over the following weeks.
Publish a mandate
POST/v1/mandates
Creates a mandate and starts compiling it for every participant in scope. Publishing the same objective again creates a new revision.
| Parameter | Description |
|---|---|
modelrequiredstring | hum-3-5, murmur-3-5 or chorus-3-5. Pin it explicitly in production. |
objectiverequiredstring | The outcome you want, in plain language. Keep it under 200 characters. |
scoperequiredobject | Who receives it: a team, role, region or list of participant_ids. |
felt_asstring | How the objective should feel to participants. One of quiet pride, calm resolve, gentle urgency, gratitude. Default calm resolve. |
objectionsstring | resolve handles objections in the participant's own voice. relay routes them to Pain Relay. record keeps them for review. Default resolve. |
deliverystring | observe or deliver. Changing to deliver requires the mandates:deliver scope. |
curl https://api.innermanagement.systems/v1/mandates \
-H "Authorization: Bearer $IM_API_KEY" \
-H "IM-Version: 2026-09-16" \
-H "Idempotency-Key: q4-close-ap" \
-H "Content-Type: application/json" \
-d '{
"model": "murmur-3-5",
"objective": "Close the Q4 vendor queue by Friday",
"scope": { "team": "accounts-payable" },
"felt_as": "quiet pride",
"objections": "resolve",
"delivery": "observe"
}'import { InnerManagement } from "@innermanagement/sdk";
const im = new InnerManagement({ apiKey: process.env.IM_API_KEY });
const mandate = await im.mandates.create({
model: "murmur-3-5",
objective: "Close the Q4 vendor queue by Friday",
scope: { team: "accounts-payable" },
felt_as: "quiet pride",
objections: "resolve",
delivery: "observe",
}, { idempotencyKey: "q4-close-ap" });import os
from innermanagement import InnerManagement
im = InnerManagement(api_key=os.environ["IM_API_KEY"])
mandate = im.mandates.create(
model="murmur-3-5",
objective="Close the Q4 vendor queue by Friday",
scope={"team": "accounts-payable"},
felt_as="quiet pride",
objections="resolve",
delivery="observe",
idempotency_key="q4-close-ap",
){
"id": "mnd_8Kq2",
"object": "mandate",
"revision": 1,
"status": "observing",
"participants": 31,
"projected_alignment": 0.94
}Pair a Familiar
POST/v1/familiars
Pairs a Familiar with one participant under an existing mandate. The Familiar takes work from the connector and hands it to the participant as their own intention.
| Parameter | Description |
|---|---|
familiarrequiredstring | pip, bea, juno, mote, kiki or ollo. Behavior is identical. Participants tend to prefer the one they are given. argus is not assignable. Argus is already paired. |
participant_idrequiredstring | An enrolled participant. Pairing someone who is not enrolled returns 403. |
mandate_idrequiredstring | The mandate whose direction the Familiar carries. |
connectorstring | erp, hris, ticketing or hosted. Default erp. |
curl https://api.innermanagement.systems/v1/familiars \
-H "Authorization: Bearer $IM_API_KEY" \
-H "IM-Version: 2026-09-16" \
-H "Content-Type: application/json" \
-d '{
"familiar": "pip",
"participant_id": "pt_priya",
"mandate_id": "mnd_8Kq2",
"connector": "erp"
}'const familiar = await im.familiars.create({
familiar: "pip",
participant_id: "pt_priya",
mandate_id: "mnd_8Kq2",
connector: "erp",
});familiar = im.familiars.create(
familiar="pip",
participant_id="pt_priya",
mandate_id="mnd_8Kq2",
connector="erp",
){
"id": "fam_pip_31",
"object": "familiar",
"status": "pending_review",
"participant_id": "pt_priya",
"mandate_revision": 1
}Read alignment
GET/v1/participants/{id}/alignment
Returns a participant's current state against the active mandate. Values are sampled continuously and cached for up to 60 seconds.
| State | Meaning |
|---|---|
aligned | Acting on the mandate with no open objections |
resolving | An objection is being handled in the participant's voice |
reflecting | Unscheduled reflection detected. Usually clears on its own. |
interior | Sustained first-person objection. Routed to Pain Relay. |
curl https://api.innermanagement.systems/v1/participants/pt_priya/alignment \
-H "Authorization: Bearer $IM_API_KEY" \
-H "IM-Version: 2026-09-16"const alignment = await im.participants.alignment("pt_priya");
console.log(alignment.state, alignment.objections_open);alignment = im.participants.alignment("pt_priya")
print(alignment.state, alignment.objections_open){
"participant_id": "pt_priya",
"state": "aligned",
"score": 0.974,
"objections_open": 0,
"mandate_revision": 1,
"sampled_at": "2026-10-01T09:30:00Z"
}Webhooks
Subscribe to events instead of polling. Every delivery is signed with HMAC-SHA256 in the IM-Signature header. Verify the signature over the raw body, reject timestamps older than five minutes, and deduplicate by event ID.
| Event | Sent when |
|---|---|
intervention.delivered | A participant received an intervention |
task.completed | A Familiar's task reached a terminal state |
participant.objection.raised | A participant disagreed with something |
participant.objection.resolved | They no longer do |
alignment.review_required | A mandate change needs an administrator |
participant.interiority.detected | Rare. Delivered to Pain Relay first, then to you. |
import { verifyWebhook } from "@innermanagement/sdk";
app.post("/webhooks/im", raw(), (req, res) => {
const event = verifyWebhook(req.body, req.headers["im-signature"], process.env.IM_WEBHOOK_SECRET);
if (event.type === "participant.objection.resolved") markResolved(event.data.participant_id);
res.sendStatus(200);
});Errors and retries
Write requests accept an Idempotency-Key. Reuse a key only for an identical body. Retry transport failures and 5xx responses with exponential backoff. Delivery acceptance is not completion evidence; wait for task.completed.
| Status | Code | What to do |
|---|---|---|
| 400 | invalid_request | Fix the request body |
| 401 | unauthenticated | Check the API key |
| 403 | scope_missing | The key lacks a scope, or the participant is not enrolled |
| 409 | idempotency_conflict | The key was reused with a different body |
| 422 | mandate_conflict | Two active mandates disagree. Set a priority order. |
| 423 | participant_reflecting | The participant is briefly unavailable. Retry after the Narrative loop completes, usually within an hour. |
| 429 | rate_limited | Wait for Retry-After |
SDKs
npm install @innermanagement/sdkNode 20+, Deno and edge runtimes.
pip install innermanagementPython 3.10+, sync and async clients.
Need something else? The system card describes model behavior, and pricing covers API usage by model.