API reference
The mngr API is organized around REST. Requests are authenticated per org, bodies are JSON, and every mutating endpoint is idempotent. Decisions issued through the API are production decisions: they are logged, traced, and binding within your org's configured governance window.
Authentication
Authenticate with your secret key using HTTP basic auth (key as username, empty password). Test-mode keys (sk_test_) issue decisions against a fixture org. Live keys (sk_live_) issue decisions against yours.
curl https://api.mngr.dev/v1/decisions \
-u sk_test_51NqRk2GLb0sMn8:Keys are org-scoped. Rotating a key does not reverse decisions issued under it.
The decision object
id string | Unique identifier, prefixed dec_. |
decision enum | One of approve, approve_with_concerns, defer, delegate, escalate. |
rationale string | A single sentence of managerial context. |
confidence number | 0–1. Calibrated weekly against realized outcomes. |
reversible boolean | Whether the decision can be reversed in-window. |
reversal_window_days integer | Defaults to 90. Reversals consume the original DU cost plus one. |
POST /v1/decisions
Creates a decision. p50 latency 141 ms.
context string, required | The situation requiring a determination. Plain prose. |
requested_by string | The user on whose behalf the decision is requested. |
urgency enum | normal or high. High-urgency decisions consume 3× DU. |
stakeholders array | Optional. Decisions with more than 6 stakeholders are escalated automatically. |
curl https://api.mngr.dev/v1/decisions \
-u sk_live_51NqRk2GLb0sMn8: \
-H "Content-Type: application/json" \
-H "Idempotency-Key: q3-headcount-0042" \
-d '{
"context": "Two teams have claimed the same Q3 headcount.",
"requested_by": "usr_8x2k1"
}'import Mngr from "mngr";
const mngr = new Mngr(process.env.MNGR_SECRET_KEY);
const decision = await mngr.decisions.create({
context: "Two teams have claimed the same Q3 headcount.",
requested_by: "usr_8x2k1",
});
decision.decision; // "defer"
decision.confidence; // 0.61import os
import mngr
client = mngr.Client(api_key=os.environ["MNGR_SECRET_KEY"])
decision = client.decisions.create(
context="Two teams have claimed the same Q3 headcount.",
)
assert decision.reversible # 90-day window by defaultResponse
{
"id": "dec_8Fk32a",
"object": "decision",
"created": 1770412800,
"decision": "defer",
"rationale": "Additional context is expected to emerge.",
"revisit_at": "2026-10-01T09:00:00Z",
"confidence": 0.61,
"reversible": true,
"reversal_window_days": 90
}POST /v1/approvals
Submits a request for approval. Chains are resolved server-side from the org graph, in order, with per-hop timeouts. A chain may visit the same approver more than once; this is expected in matrixed organizations.
type enum, required | One of expense, purchase, access, exception. |
amount_usd number | Required for monetary types. |
requester string, required | The user requesting approval. |
memo string | Free-text context, visible to every hop in the chain. |
Response — 202 Accepted
{
"id": "apr_0kq3k1",
"object": "approval",
"status": "pending",
"amount_usd": 41.50,
"approver_chain": ["mgr_2231", "mgr_0417", "mgr_2231"],
"position_in_queue": 4
}POST /v1/one-on-ones
Creates a recurring one-on-one between a manager instance and a report. Either party may reschedule a session. reschedule_count is preserved across reschedules and cannot be reset.
report string, required | The user the one-on-one is for. |
manager string | Defaults to the report's assigned manager instance. |
recurrence enum | One of weekly, biweekly, monthly. Defaults to weekly. |
Response — 201 Created
{
"id": "ooo_2m81xk",
"object": "one_on_one",
"status": "scheduled",
"scheduled_for": "2026-08-12T14:30:00Z",
"duration_minutes": 30,
"agenda": ["Career growth", "Q3 priorities", "Open items"],
"reschedule_count": 3
}GET /v1/priorities
Returns the org's current priority stack, ordered. This endpoint takes no parameters. All levels are P0 by default; additional levels are available on Enterprise.
Response — 200 OK
{
"object": "list",
"url": "/v1/priorities",
"data": [
{ "id": "pri_g81m2", "name": "Migration to v2 decision schema", "level": "P0" },
{ "id": "pri_g81m3", "name": "Q3 hiring plan", "level": "P0" }
],
"has_more": true
}POST /v1/feedback
Composes performance feedback in the org's configured format. The default format is sandwich. The delivered field remains false until the feedback is delivered, which is outside the scope of the API.
subject string, required | The user the feedback concerns. |
channel enum | One of written, verbal. verbal is not yet implemented. |
topic string | Narrows the feedback to one area of performance. |
Response — 200 OK
{
"id": "fdb_9k2m1x",
"object": "feedback",
"format": "sandwich",
"segments": [
{ "tone": "positive", "text": "Your throughput this quarter has been strong." },
{ "tone": "developmental", "text": "Review turnaround is trending 40% above team median." },
{ "tone": "positive", "text": "Your throughput this quarter has been strong." }
],
"delivered": false
}Idempotency
Send an Idempotency-Key header with any POST. Replaying a request returns the original decision with idempotency-status: replayed. Asking the same question again does not change the answer.
Rate limits
60 decisions per minute per org by default. Sustained load above the limit degrades confidence scores before it degrades availability. Decision outcomes shift measurably across an unbroken session (Danziger et al., PNAS 2011). The limiter exists to protect calibration. 429 responses set Retry-After.
Errors
mngr uses conventional HTTP status codes. Machine-readable codes appear in error.code.
400 invalid_request_error | The body is malformed or a required parameter is missing. |
401 authentication_error | The API key is missing, invalid, or revoked. |
402 quota_exceeded | The org's decision-unit balance is exhausted for the period. |
404 resource_missing | No resource exists with that id. |
409 MANAGER_CONFLICTED | The assigned manager instance holds both positions on this decision. Retry after the conflict window closes. |
422 decision_not_actionable | The context was insufficient to form a determination. |
429 rate_limited | Too many decisions. See Retry-After. |
500 internal_error | Something failed on our side. The decision will be reissued. |
Webhooks
Register an HTTPS endpoint to receive events. Payloads are signed with an HMAC in the mngr-signature header. Events: decision.created, decision.reversed, approval.resolved, oneonone.rescheduled, reorg.
mngr.webhooks.on("reorg", async () => {
// The reorg event has no payload.
await refetchAllResources();
});The reorg event has no payload schema. Consumers are advised to re-fetch all resources.
Changelog
2026-06-15 | Current version. Confidence scores now round half away from zero. |
2026-05-20 | Rate-limit headers renamed to the IETF draft standard names. |
2026-03-02 | Added the delegate decision type. A decision may now resolve to the decision being made elsewhere. |
2025-11-01 | DELETE /v1/morale now returns 410 Gone. |