Skip to main content
Records writes are governed commands, such as “add a note to this record” or “set this record’s status”. Nexio records each command in the action ledger: an append-only record of every command your people issued, kept for your organization. Current notes, tasks and statuses are projections of that ledger, and you read them back through their own routes.
Nothing is written to the connected system of record today. A note or task you record appears in Nexio’s reads and in applications built on them. It does not appear in the source system. Routes that would change the source system refuse with 403 overlay_read_only (see What is refused).

How it works

  1. Your server sends POST /api/v1/records/actions with the person the commands are for (actor_principal) and 1 to 20 commands.
  2. When a command addresses a record of the system of record, Nexio resolves that person’s authority as it does for a read (see Authority and scope), and each such command must address a record the person may open. A note on a Catalog entity needs no system-of-record authority: a batch whose commands all address Catalog entities resolves no connection, and its response carries no serving block.
  3. Nexio applies the whole batch in one transaction. If any command fails, none is recorded.
  4. Each command gets a sequence number (seq) in the organization’s ledger. The response returns them with action_seq, the ledger’s latest sequence number.
  5. You read the current state back from /notes, /tasks or /workflows, or follow the ledger itself from /actions. These three reads return the state of system-of-record records for one connection; a note on a Catalog entity appears only in the ledger read (/actions).

Commands

The command set is fixed in code: 14 commands, and no organization adds its own. Ten of them are the commands you send: The other four are not yours to send: source_activity.create and renewal_decision.set are refused with 403 overlay_read_only (What is refused), and book_edit_intent.transition and book_edit_intent.cancel are internal, so a batch that names one answers 400 action_schema_unknown. Every command carries command, schema_rev (always 1 today), exactly one target, a payload, and an idempotency_key. A target is a client_key or a policy_key, the opaque keys the system of record’s rows carry, or, for notes only, a Catalog entity (catalog_entity_type plus catalog_id). Payloads are validated strictly: an unknown field is refused. A command’s optional id must be a UUID. When you omit it, Nexio generates one, and for note.create and task.create that id becomes the note or task id. status.set writes one registered workflow field on one record. The fields, the record kind each applies to, and their allowed values are fixed in code. An unknown field, or a value the field does not allow, answers 400 action_payload_invalid.

Idempotency and safe retries

  • Every command needs an idempotency_key, a UUID you generate. It is unique across your organization’s ledger.
  • Sending the same key again with the same command, target, payload, actor and basis records nothing new. The response returns the original command_id and seq with "idempotent_replay": true, and the status is still 200.
  • Sending the same key with anything different answers 400 action_payload_invalid.
  • So a timed-out batch is safe to resend unchanged. Generate new keys only for new intent.
The optional basis names the ledger position the person was looking at (seq, from a previous action_seq). A stale basis does not cause a refusal. When another command changed the same note, task or status after that position, the projection marks the row applied_over_concurrent: true so your application can tell the person.

Scope-bounded writes

  • actor_principal is the person the commands are for. actor_type is producer (a person) or agent (an AI agent acting for that person).
  • If you send X-Nexio-Acting-Principal, it must equal actor_principal, or the request answers 400 invalid_request. If you omit it, Nexio resolves authority for actor_principal.
  • A command addressing a record outside that person’s authority answers 403 action_out_of_scope, and the whole batch is refused.
  • A session with X-Nexio-Records-Lens cannot write: 403 book_lens_read_only.

Example: record a note and a task

200 OK
Sending the same request again returns the same command_id and seq values, each with "idempotent_replay": true. On the action routes serving.as_of and serving.source.fetched_at are the zero time, even when the scope check for a command that addresses a system-of-record record queries the warehouse.

Read it back

Deleted notes and tasks are hidden from the projections. A row about a policy record identifies it by the source’s tenant key and record id (ams360_datasource and policy_id) rather than by policy_key. A person whose scope is Self sees only ledger rows they authored on /actions; an All or Platform scope sees the whole ledger.
200 OK
attach_status is attached on every row written today.

What is refused

These write paths exist and always refuse, because they would change the system of record:

Limits

Errors

Authority refusals (identity_unmapped, scope_unavailable and the rest) are listed on Authority and scope. Read-time failures (book_unavailable) are on Completeness and errors.

Next

Append commands

Endpoint reference.

Authority and scope

How the person’s authority is resolved.
Last modified on September 25, 2026