Access, actors and audit
A coding agent that configures billing needs enough access to do the job and not enough to cause damage. Runledger gives it scoped credentials, records every change with who made it, and keeps a log a person can read.
Keys and scopes
A secret key (rl_sk_...) has full access to its environment. A restricted key (rl_rk_...) carries a list of scopes, an optional expires_at, and an agent flag that marks a key issued to an agent. OAuth sessions from the MCP server carry the same scopes.
An agent key that holds spend_limits:write or auto_top_up:write can create a customer’s limit or lower it in live mode, and is refused with permission_denied when it tries to raise or remove one. Agent keys can’t create customer sessions. These are the only live data writes an agent key can hold, and neither is in a preset.
A call outside a key’s scopes returns 403 with code: insufficient_scope and required_scope naming what it needed. An MCP client can answer that by asking the person to widen the grant, which is the step-up flow the MCP authorization spec describes.
GET /v1/api_keys lists keys, masked: name, type, prefix, scopes, agent, expiry and last use, never the secret. It lets an agent see what it holds. Agents never create, roll or revoke keys, and never receive live provider credentials. People do that in the dashboard: an Admin for live keys, and an Admin or a Collaborator for sandbox keys.
Who did it
Every change records an actor: {type, id, name, on_behalf_of, client}.
Runledger fills the actor in from the credential, and a client can’t claim to be someone else. An API key always acts as itself, a secret key included, and the dashboard calls the API as the signed-in person, so approving a proposal or removing a live provider needs an Admin signed in to the dashboard. A request that sends a Runledger-Actor header is refused with 400 parameter_unknown. actor appears on request logs, reversals, dispute decisions, credit grants and voids, outcome definition versions, plans, webhook endpoints, payment providers, routing and notification rules, and config proposals. Request logs filter by actor_type, actor and key, so you can list everything an agent did.
Request logs
GET /v1/request_logs lists the requests made with your keys in the last 30 days, with the status, the error code, the idempotency key, the actor and the bodies. Secrets are redacted before a request is stored: a webhook signing secret and every link that grants access (a checkout page, a customer view link, an export download, an invoice’s payment page, a provider’s connect page) read [redacted]. Other fields are kept as sent. A configuration write sent with Runledger-Dry-Run: true is logged like any other request, and appears tagged Dry run, so you can tell a check from a change. The dry run writes nothing. When the same change is later made for real, that request is logged on its own, and the audit event it creates has dry_run_preceded: true.
The audit log
GET /v1/audit_events records what changed, who changed it, and through which surface (dashboard, api or mcp). Each event has the action, the resource and its version, the field changes, the request_id, and dry_run_preceded, which is true when the same change was dry-run or validated first. The dry run itself is in the request logs, tagged Dry run. A change made by approving a config proposal also carries approved_by, the signed-in Admin who approved it and when. actor stays the one who made the request, such as the agent or the Collaborator that proposed it. An Admin can approve any proposal, including one for notification or routing rules. Events are kept for at least 13 months, and the log needs the audit:read scope.
Besides configuration changes, these write an audit event with the actor:
The changes on an auto top-up event show the fields before and after, so you can see who raised a monthly_limit. Holding a price change writes no configuration, which is why it has an event of its own. Choosing follow instead, or editing the rule, is an ordinary price rule change and is recorded as one. Filter by actor_type, actor, resource, source and time.
See also
- Configuration covers proposals for live changes.
- Set up with a coding agent lists the scope each tool needs.
- The dashboard lists the roles, including who approves proposals and who changes a customer’s limits.