---
title: "Create Event Block"
method: POST
path: "/extensions/roboledger/{graph_id}/operations/create-event-block"
tags: ["RoboLedger: Ledger & Events"]
---

# Create Event Block

`POST /extensions/roboledger/{graph_id}/operations/create-event-block`

## Request

- Base URL: `https://api.robosystems.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.robosystems.ai/extensions/roboledger/{graph_id}/operations/create-event-block`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Persist a real-world business event. apply_handlers=False (default): capture-only, status='captured'. apply_handlers=True: resolves an event_handler, fires the template, creates GL entries atomically, status='classified'. Use preview-event-block to dry-run before committing. For journal_entry_recorded, whether the entry writes back to a connected source system follows `source` (schedule/manual publish; system does not) unless metadata.publish_to_source says otherwise — set it false for an alignment entry mirroring a change already made upstream, which would otherwise be applied twice.

**Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict.

## Path parameters

- `graph_id` string, required

## Headers

- `Idempotency-Key` string, nullable

## Request body

- CreateEventBlockRequest: Write surface for a single business event.
  - `entity_id` string, nullable: The entity whose books the event lands in, by id; every GL row its handler writes follows it. Omit for the group parent.
  - `event_type` string, required: Open vocabulary: 'invoice_issued' | 'contract_signed' | 'bank_transaction' | ...
  - `event_category` 'sales' | 'purchase' | 'financing' | 'payroll' | 'treasury' | 'adjustment' | 'recognition' | 'other' | 'control' | 'approval' | 'reconciliation' | 'inquiry', required: REA classification. Economic categories (sales, purchase, financing, payroll, treasury, adjustment, recognition, other) require event_class='economic'. Support categories (control, approval, reconciliation, inquiry) require event_class='support'. The DB CHECK rejects mismatched pairings.
  - `event_class` 'economic' | 'support': REA event class. 'economic' events change resources and drive GL postings; 'support' events are audit-trail / value-chain primitives (typically captured with apply_handlers=False).
  - `event_action` 'produce' | 'raise' | 'consume' | 'lower' | 'use' | 'cite' | 'work' | 'deliverService' | 'pickup' | 'dropoff' | 'accept' | 'transferCustody' | 'transferAllRights' | 'transfer' | 'move' | 'modify' | 'combine' | 'separate' | 'copy', nullable: Canonical action verb refining `event_category`. Disambiguates concepts ERPs collapse: `transferAllRights` (ownership transfer, no physical movement) vs `transferCustody` (physical only, no rights transfer) — load-bearing for consignment, drop-shipping, marketplace settlement, escrow. Optional; null is valid for legacy events and during adapter rollout.
  - `agent_id` string, nullable: ID of the counterparty agent (customer, vendor, employee, lender) involved in the event. `null` for internal-only events.
  - `resource_type` 'goods' | 'services' | 'money' | 'right' | 'obligation' | 'information' | 'labor', nullable: REA resource kind being exchanged. One of: `goods`, `services`, `money`, `right`, `obligation`, `information`, `labor`.
  - `resource_element_id` string, nullable: ID of the specific element being exchanged, when known (e.g. the cash account for a treasury movement, the inventory item for a sale).
  - `occurred_at` string, date-time, required: When the event happened in the real world
  - `effective_at` string, date-time, nullable: Accounting recognition date, if different from occurred_at
  - `source` string, required: 'manual' | 'system' | 'schedule', a connected provider name (e.g. 'quickbooks'), or a source_name registered via an 'external' connection. Validated against the graph's registered connections.
  - `external_id` string, nullable: Source-system dedup key. (source, external_id) is enforced unique when external_id is provided, so retries from external adapters are idempotent at the DB level.
  - `external_url` string, nullable: Deep link back to source-system record
  - `amount` integer, nullable: Economic value of the event in **cents** of `currency`, signed. Sign convention follows the perspective of the entity that owns the graph: inflows positive, outflows negative. `null` for non-economic events (e.g. `event_class='support'`).
  - `currency` string: ISO 4217 currency code for `amount`.
  - `description` string, nullable: Free-text human-readable summary of the event.
  - `metadata` object: Free-form payload, opaque to the event surface. When `apply_handlers=True`, the matched handler's metadata schema validates this dict — required keys depend on the handler registered for `event_type`. Use `preview-event-block` to discover the expected shape without writing.
  - `dimension_ids` string[]: IDs of dimension members tagging this event (e.g. department, fund, project). Propagate to the GL entries produced by the handler.
  - `obligated_by_event_id` string, nullable: Forward-materialization link: the event that scheduled or obligated this one (e.g. depreciation entries point at the asset_acquired event).
  - `discharges_event_id` string, nullable: Settlement link: the obligation this event discharges (e.g. cash_received pointing at the originating sale_invoiced).
  - `document_id` string, nullable: The stored document this event rests on, as evidence: the invoice PDF, the vendor bill, the receipt photo (upload it with create-document-upload and complete-document-upload). Must be a document on this graph. While the event is live, the document cannot be deleted.
  - `apply_handlers` boolean: When True, resolves the event_type to a handler (Python registry first, then DSL) and fires it atomically with event creation.

## Response `200`

Successful Response

- OperationEnvelopeEventBlockEnvelope
  - `operation` string, required: Kebab-case operation name
  - `operationId` string, required: op_-prefixed ULID for audit and SSE correlation
  - `status` 'completed' | 'pending' | 'failed', required: Operation lifecycle state
  - `result` EventBlockEnvelope: Read projection for a single event block. Returned by `create-event-block`, `update-event-block`, `preview-event-block`, and the read-side `get-event-block`. Mirrors the request shape plus server-assigned fields (id, status, audit timestamps) and the four nullable correction/duality links.
    - `id` string, required: Event ID (`evt_*` ULID).
    - `event_type` string, required: Open-vocabulary event type (e.g. `invoice_issued`, `bank_transaction`, `control_executed`).
    - `event_category` string, required: REA category, scoped by `event_class` — economic (`sales`, `purchase`, `financing`, `payroll`, `treasury`, `adjustment`, `recognition`, `other`), support (`control`, `approval`, `reconciliation`, `inquiry`), or operational (`pipeline`, `engagement`, `schedule`, `other`) for occurrences that drive no GL — a lead, a lifecycle change, an outreach, a schedule setup.
    - `status` string, required: Lifecycle state. One of: `captured` (raw, pre-classification), `classified` (handler ran, GL pending), `committed` (GL entries posted), `pending` (committed but awaiting fulfillment of an obligation), `fulfilled` (obligation discharged — retractable while its ledger rows are still drafts), `voided` (canceled — terminal), `superseded` (replaced by a corrected event — terminal). See `UpdateEventBlockRequest.transition_to` for the valid transition graph.
    - `occurred_at` string, date-time, required: When the event happened in the real world (UTC).
    - `effective_at` string, date-time, nullable: Accounting recognition date, when different from `occurred_at`.
    - `source` string, required: Capture source: `manual`, `system`, `schedule`, a connected provider name (e.g. `quickbooks`), or a registered external source_name. Used for adapter routing.
    - `external_id` string, nullable: Source-system dedup key. Unique with `source` when set, so adapter retries are idempotent.
    - `external_url` string, nullable: Deep link back to the source-system record.
    - `amount` integer, nullable: Economic value in **cents** of `currency`, signed (inflows positive, outflows negative). `null` for non-economic events.
    - `currency` string, required: ISO 4217 currency code for `amount`.
    - `description` string, nullable: Free-text human-readable summary.
    - `metadata` object, required: Free-form payload — handler-specific keys when the event ran through a handler, otherwise whatever the adapter captured.
    - `is_reconciling_item` boolean: True when this event is a reconciling item: a source re-sync surfaced a changed upstream payload for an event whose GL is already posted (committed/fulfilled are immutable to sync) — the local books legitimately no longer mirror the source, and the difference awaits an explicit disposition (restate the affected months, or book a catch-up entry in the open period). The live payload and GL are untouched; the incoming payload is stashed in `metadata.drift_payload` with `metadata.drift_detected_at`.
    - `dimension_ids` string[], required: Dimension-member IDs tagging this event (department, fund, project). Propagate to GL entries produced by the handler.
    - `event_class` string, required: REA event class — `economic` (drives GL postings) or `support` (audit-trail / value-chain primitive, no GL impact).
    - `event_action` 'produce' | 'raise' | 'consume' | 'lower' | 'use' | 'cite' | 'work' | 'deliverService' | 'pickup' | 'dropoff' | 'accept' | 'transferCustody' | 'transferAllRights' | 'transfer' | 'move' | 'modify' | 'combine' | 'separate' | 'copy', nullable: Canonical action verb refining `event_category`. Null when the source adapter or capture path didn't supply one.
    - `agent_id` string, nullable: Counterparty agent ID, when the event involves one.
    - `resource_type` string, nullable: REA resource kind being exchanged (`goods`, `services`, `money`, `right`, `obligation`, `information`, `labor`).
    - `resource_element_id` string, nullable: Specific element ID being exchanged, when known.
    - `replaced_by_event_id` string, nullable: ID of the event that replaces this one. Set when this event was superseded (`status='superseded'`); points forward in the correction chain.
    - `replaces_event_id` string, nullable: ID of the event this one replaces, when applicable. Points backward in the correction chain. Mirror of `replaced_by_event_id` on the predecessor.
    - `obligated_by_event_id` string, nullable: Forward-materialization link — the event that scheduled or obligated this one (e.g. depreciation entries point at the originating `asset_acquired` event).
    - `discharges_event_id` string, nullable: Settlement link — the obligation this event discharges (e.g. `cash_received` pointing at the originating `sale_invoiced`).
    - `document_id` string, nullable: The stored document the event rests on (an invoice, a bill, a receipt, a statement); read it with get-document.
    - `created_at` string, date-time, required: Row creation timestamp (UTC).
    - `created_by` string, required: ID of the user who captured the event. For adapter-sourced events, the system actor associated with the adapter.
  - `at` string, required: ISO-8601 UTC timestamp
  - `createdBy` string, nullable: User ID that initiated the operation
  - `idempotentReplay` boolean: True when this envelope came from the idempotency cache — the underlying command did not execute again. False on fresh executions.

## Other responses

- `400`: Invalid request
- `401`: Authentication required
- `403`: Access denied
- `404`: Resource not found
- `409`: Idempotency-Key conflict — key reused with different body
- `422`: Validation error
- `429`: Rate limit exceeded
- `500`: Internal server error

---

[API](https://skmtc.dev/robosystems/apis/robosystems-api.md) · [All operations](https://skmtc.dev/robosystems/apis/robosystems-api/llms.txt) · [OpenAPI document](https://skmtc.dev/robosystems/apis/robosystems-api/revisions/e661e2d5ca6a?raw)
