Browse the extensions reference

Create Event Handler

post/extensions/roboledger/{graph_id}/operations/create-event-handler

Part of RoboLedger: Ledger & Events.

Define a rule that fires GL transactions when a matching event block is created with apply_handlers=True. Match criteria (event_type, event_category, match_source, match_agent_type, etc.) act as AND-joined filters — null fields match anything. The highest-priority matching handler wins. A handler created through an AI client is the AI's suggestion (suggested_by='ai'): it takes no part in matching until a person approves it in the app or the API.

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.

Authentication

Authenticate in any one of these ways — not all of them:

  • API key in the X-API-Key header.
  • Bearer token in the Authorization header.

Path parameters

NameTypeDescription
graph_idrequiredstringGraph Id

Constraints: matches ^(kg[a-f0-9]{16,}(?:_[a-zA-Z0-9]{1,20})?|sec(?:_[a-zA-Z0-9]{1,20})?|library)$

Header parameters

NameTypeDescription
Idempotency-KeyoptionalstringIdempotency-Key

Request body

Required, application/json.

FieldTypeDescription
namerequiredstring

Human-readable handler name (unique per graph).

descriptionoptionalstring

Free-form description shown in admin UIs.

event_typerequiredstring

Event type to match. Matches the event_type field on incoming events from create-event-block.

event_categoryoptionalstring

Optional category filter (e.g. 'expense', 'revenue').

match_sourceoptionalstring

Match the event's source field (e.g. 'quickbooks', 'plaid'). Useful when the same event_type comes from multiple integrations.

match_agent_typeoptionalstring

Match agent-emitted events by agent_type.

match_resource_typeoptionalstring

Match resource-bound events by resource_type.

match_metadata_expressionoptionalobject

JSONPath-style equality map against event.metadata, e.g. {"category": "payroll"} or {"metadata.category": "payroll"}

transaction_templaterequiredTransactionTemplate

The DSL spec for the GL rows this handler produces. See TransactionTemplate for the shape.

TransactionTemplate fields
FieldTypeDescription
transactionsrequiredTransactionTemplateItem[]

At least one debit/credit entry pair

Constraints: at least 1 item

TransactionTemplateItem fields
FieldTypeDescription
entry_templaterequiredTransactionTemplateEntry

One balanced entry (debit + credit pair) — the inner shape of entry_template.

priorityoptionalinteger

Tiebreaker when multiple equally-specific handlers match. Higher = wins.

Default: 0

is_activeoptionalboolean

Inactive handlers are ignored at match time.

Default: true

originoptionalstring

Provenance of the handler. tenant = authored on this graph, the only value a caller may set; hub = platform-shipped template.

One of: hub, tenant

Default: tenant

metadataoptionalobject

Free-form metadata stored alongside the handler.

Example request

curl · example 1 of 2
curl -X POST "https://api.robosystems.ai/extensions/roboledger/{graph_id}/operations/create-event-handler" \
  -H "X-API-Key: $ROBOSYSTEMS_API_KEY" \
  -H "Idempotency-Key: <Idempotency-Key>" \
  -H "Content-Type: application/json" \
  -d '{
  "event_type": "vendor_bill_received",
  "match_source": "quickbooks",
  "name": "QB Vendor Bill — Default Expense Posting",
  "priority": 0,
  "transaction_template": {
    "transactions": [
      {
        "entry_template": {
          "credit": {
            "amount": "{{ event.amount }}",
            "element_id": "elem_coa_accounts_payable"
          },
          "debit": {
            "amount": "{{ event.amount }}",
            "element_id": "elem_coa_office_supplies"
          }
        }
      }
    ]
  }
}'
curl · example 2 of 2
curl -X POST "https://api.robosystems.ai/extensions/roboledger/{graph_id}/operations/create-event-handler" \
  -H "X-API-Key: $ROBOSYSTEMS_API_KEY" \
  -H "Idempotency-Key: <Idempotency-Key>" \
  -H "Content-Type: application/json" \
  -d '{
  "event_category": "expense",
  "event_type": "payroll_run_completed",
  "match_metadata_expression": {
    "category": "payroll"
  },
  "name": "Payroll Run — Wages + Tax Liability",
  "priority": 10,
  "transaction_template": {
    "transactions": [
      {
        "entry_template": {
          "credit": {
            "amount": "{{ event.amount }}",
            "element_id": "elem_coa_wages_payable"
          },
          "debit": {
            "amount": "{{ event.amount }}",
            "element_id": "elem_coa_wages_expense"
          }
        }
      },
      {
        "entry_template": {
          "credit": {
            "amount": "{{ event.metadata.tax_cents }}",
            "element_id": "elem_coa_payroll_tax_liability"
          },
          "debit": {
            "amount": "{{ event.metadata.tax_cents }}",
            "element_id": "elem_coa_payroll_tax_expense"
          }
        }
      }
    ]
  }
}'

Responses

200 Successful Response

FieldTypeDescription
operationrequiredstring

Kebab-case operation name

operationIdrequiredstring

op_-prefixed ULID for audit and SSE correlation

statusrequiredstring

Operation lifecycle state

One of: completed, pending, failed

resultoptionalEventHandlerResponse

Command-specific result payload

EventHandlerResponse fields
FieldTypeDescription
idrequiredstring

Handler id (hdl_-prefixed).

namerequiredstring

Human-readable handler name.

descriptionoptionalstring

What the handler is for.

event_typerequiredstring

The event type the handler matches.

event_categoryoptionalstring

Match on the event's category; null matches any.

match_sourceoptionalstring

Match on the event's source system; null matches any.

match_agent_typeoptionalstring

Match on the counterparty's role; null matches any.

match_resource_typeoptionalstring

Match on the resource type; null matches any.

match_metadata_expressionoptionalobject

Equality matches against the event's metadata.

transaction_templaterequiredobject

The GL rows the handler books: its DSL template, as JSON.

priorityrequiredinteger

Among handlers that match, the highest priority wins.

is_activerequiredboolean

Whether the handler takes part in matching at all.

originrequiredstring

hub for a platform-shipped handler, tenant otherwise.

suggested_byoptionalstring

ai when an AI client created the handler or last changed what it matches or books; null when a person did.

confidenceoptionalnumber

The suggesting AI's confidence, when it gave one.

approved_byoptionalstring

The user who approved an AI-suggested handler.

approved_atoptionalstring (date-time)

When it was approved.

awaiting_approvaloptionalboolean

True for an AI-suggested handler no one has approved: it takes no part in matching until a person approves it.

Default: false

created_atoptionalstring (date-time)

When it was created.

updated_atoptionalstring (date-time)

When it last changed.

created_byoptionalstring

The user who created it.

atrequiredstring

ISO-8601 UTC timestamp

createdByoptionalstring

User ID that initiated the operation

idempotentReplayoptionalboolean

True when this envelope came from the idempotency cache — the underlying command did not execute again. False on fresh executions.

Default: false

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