Factuarea APIDevelopers

Usage

The factuarea command tree — list, show, create, domain actions, binary downloads, multipart uploads, the generic api escape hatch and the commands --json manifest.

The command tree covers every resource in the API (factuarea <resource> [<sub-resource>] <action>), generated from the OpenAPI spec so it never drifts from the live surface.

Reading data

# List (with automatic cursor pagination)
factuarea invoices list --json
factuarea contacts list --paginate --json

# Get one
factuarea invoices show <uuid> --json

--json emits the raw API body on stdout. --paginate walks every page for you, following next_cursor until has_more is false. See Pagination for the underlying cursor semantics.

Writing data

Pass the JSON body with -d (inline) or --data-file (a path). The API computes totals — do not pre-round them.

factuarea invoices create -d '{"client_id":"…","series_id":"…","lines":[…]}'

Every mutation gets an automatic Idempotency-Key so a retried request never double-creates a resource. See Idempotency.

Domain actions

State changes are discrete actions, not a generic status flag — mirroring the API's own design:

factuarea invoices send <uuid>
factuarea invoices mark-paid <uuid>

Some actions are irreversible (deletes, void, conversions, fiscal emission). The CLI asks you to confirm them before the call — see Irreversible operations and the scopes & irreversibility guide.

Time tracking (control-horario)

The control-horario add-on adds workforce resources — employees, work schedules, time entries, absences, presence, holidays, monthly closes and the gestoría summary. Each command is generated from the spec and gated by its fine-grained scope (employees:*, time_entries:*, absences:*, work_schedules:*, presence:read, holidays:read, payroll_exports:*).

# Clock an employee in and out — every entry is hash-chained (RD-ley 8/2019)
factuarea time-entries clock-in  -d '{"employee_id":"…","source":"web"}'
factuarea time-entries clock-out -d '{"employee_id":"…","source":"web"}'

# Request time off, then approve it
factuarea absence-requests create \
  -d '{"employee_id":"…","absence_type_id":"…","start_date":"2026-08-01","end_date":"2026-08-05"}'
factuarea absence-requests approve <uuid>

# Live team presence right now
factuarea presence live --json

# Close a month's immutable register, then export it (ITSS RD-ley 8/2019)
factuarea monthly-time-record-closes create -d '{"year":2026,"month":7}'
factuarea monthly-time-record-closes export <uuid> --format rdley_8_2019 --json

Automations

The automations add-on exposes the rule engine: a rule listens to an event, a condition decides whether to act, and an ordered list of actions runs. The module gates the whole group, and each command carries its fine-grained scope — automations:read (8 commands), automations:write (6), automation_runs:read (3) and automations:delete (1). Four subgroups mirror the API: catalog, rules (with rules versions), runs (with runs steps) and usage. See the Automations guide for the model.

Start at the catalog. The evaluable fields of a trigger are a second call, one per trigger — they do not travel inside the catalog:

# What can be automated: triggers, operators and registered actions.
factuarea automations catalog show --json

# The evaluable fields of one trigger.
factuarea automations catalog trigger-fields invoice.paid --json

Creating a rule goes through the full JSON body. actions is a list of objects, so no typed flag is generated for it, and the binary refuses to mix field flags with -d/--data-file — pick one. --skeleton prints the template of the body without calling the API:

factuarea automations rules create --skeleton
{
  "actions": [],
  "conditions": {
    "<key>": "<string>"
  },
  "description": "<string>",
  "name": "<string>",
  "scope": "<empresa|cartera>",
  "trigger_type": "<string>"
}
# Fill it in and send it whole. `scope` is chosen here and cannot be changed later.
factuarea automations rules create --json -d '{
  "name": "Warn me on a large payment",
  "scope": "empresa",
  "trigger_type": "invoice.paid",
  "conditions": {"field": "total", "operator": "gte", "value": 1000},
  "actions": [
    {"type": "notify_in_app", "order": 0, "parameters": {
      "recipient_type": "role", "role": "admin", "category": "invoice",
      "title": "Large payment", "message": "An invoice over 1000 EUR has been paid"
    }}
  ]
}'

# Dry-run it against a sample event: it returns the trace per step and materialises nothing.
factuarea automations rules dry-run <rule_id> --json \
  -d '{"event_type":"invoice.paid","event_payload":{"total":1200,"status":"paid"}}'

# A rule is created in draft and fires nothing until you activate it.
factuarea automations rules activate <rule_id>
factuarea automations rules pause <rule_id>

# Read one, and edit it — every edit seals a new version.
factuarea automations rules show <rule_id> --json
factuarea automations rules update <rule_id> --json -d '{"name":"Warn me on a payment over 2000"}'

# List with filters, walking the cursor for you.
factuarea automations rules list --paginate --json
factuarea automations rules list --status active --trigger_type invoice.paid --json

# Only the portfolio rules of an accounting firm.
factuarea automations rules list --scope cartera --json

# The sealed versions of the definition.
factuarea automations rules versions list <rule_id> --json
factuarea automations rules versions show <rule_id> 2 --json

# What fired, and what each step did.
factuarea automations runs list --paginate --json
factuarea automations runs list --automation_rule_id <rule_id> --status failed --json

# What a portfolio rule did on one managed company.
factuarea automations runs list --subject_company_id <company_id> --json
factuarea automations runs show <run_id> --json
factuarea automations runs steps list <run_id> --json

# Consumption against the plan budget for the period.
factuarea automations usage show --json

Four listings paginate by cursor — rules list, rules versions list, runs list and runs steps list — and --paginate walks every page for you. The version history is the only one whose cursor is an opaque numeric string instead of a UUID, because it paginates by position; pass back the next_cursor you were given and never build one yourself.

Three commands of this group are irreversible and refuse to guess:

# Replay runs the parked work again FOR REAL: it sends email and delivers webhooks.
factuarea automations runs replay <run_id> --confirm <run_id>
factuarea automations runs steps replay <run_id> 0 --confirm 0

# Deleting a rule stops it firing for good; its versions and runs stay auditable.
factuarea automations rules delete <rule_id> --confirm <rule_id>

--confirm takes the last positional argument of the command: the rule id for rules delete, the run id for runs replay and the step index for runs steps replay. Without a TTY (or with --no-input) and without --confirm, the command exits 2 instead of guessing. On top of that, every mutation made with a fact_live_ key needs the explicit --live flag — see Test mode and Irreversible operations.

Binary downloads and uploads

PDF, ZIP and XML endpoints stream a binary you save with -o. Multipart uploads take the file with a --file-<field> flag:

# Download a PDF
factuarea invoices pdf <uuid> -o invoice.pdf

# Upload a certificate (multipart)
factuarea verifactu certificates upload \
  -d '{"certificate_password":"…"}' --file-certificate_file cert.p12

The api escape hatch

Any endpoint is reachable directly with factuarea api <method> <path>, even ones without a dedicated command yet:

factuarea api get /v1/account --json
factuarea api post /v1/invoices -d '{…}'

The command manifest

factuarea commands --json dumps the full manifest of commands in one call — path, args, flags, whether each mutates, whether it is binary or paginated, its required scope, whether it is irreversible, and an example. An agent discovers the entire surface in a single call:

factuarea commands --json

See Agents & scripting for the manifest fields and the JSON contract.

Embedded API reference

A quick API reference travels with the binary — searches stay on your machine:

factuarea docs search invoice

docs search reads the OpenAPI spec embedded in the binary and answers "which command do I call?". It returns operations — command, summary, method and path — and never touches the network.

Searching the published docs

docs list, docs grep and docs get read the published documentation — the llms-full corpus of docs.factuarea.com — and answer "what do the docs say about this?". They return pages and sections, from the guides, the API reference and the error catalog:

factuarea docs list                    # every page: <path> — <title>
factuarea docs list /guides            # only the ones under that prefix
factuarea docs grep "idempotency-key"  # documentation sections that match
factuarea docs get /guides/idempotency # the whole page, as Markdown

The corpus is downloaded whole and once, stored in the system cache directory (~/Library/Caches/factuarea/docs/ on macOS, ~/.cache/factuarea/docs/ on Linux) and filtered locally. While the copy is younger than 15 minutes no network request happens at all, so a session that chains list, grep and get downloads once.

Your search term never leaves the machine. The URL fetched is fixed and does not depend on what you type — there is no search server at the other end. None of the four docs subcommands reads or sends an API key.

OptionWhat it does
--refreshDownloads again, ignoring a copy that is still valid
--langLanguage of the guides: en, es or ca (default en, the source language). The API reference is not translated and always comes through
--jsonStable output on stdout: path/title for list, path/title/section/snippet for grep, path/title/markdown for get

If the download fails and a cached copy exists — even an expired one — that copy is used, a warning goes to stderr so the JSON on stdout stays parseable, and the exit code is 0. With no copy at all, the exit code is 10 (network). Set FACTUAREA_DOCS_URL to fetch the corpus from another origin.

REST fallback

The CLI’s command catalog comes from its bundled spec. In the September 2026 baseline, release v0.2.0 is available and the main-branch spec contains 414 entries, with 38 REST endpoints absent from generated commands. Inspect factuarea commands --json for your installed version. Use the raw HTTP command for a supported REST endpoint missing from that catalog:

factuarea api get /v1/stores

On this page

Need a hand?Contact support