Automatitzacions
El model quan, si i fes del motor de regles — versions, l'assaig que no materialitza res, l'historial d'execucions i els seus passos, el rellançament, els límits del motor i les regles de cartera per a gestories.
El motor d'automatitzacions converteix un esdeveniment en feina. Una regla
escolta un tipus d'esdeveniment, una condició decideix si aquell esdeveniment
concret és el seu cas, i s'executa una llista ordenada d'accions. Tot penja de
https://api.factuarea.com/v1/automations, requereix el mòdul automations del
pla i fa servir quatre scopes fins: automations:read, automations:write,
automations:delete i automation_runs:read. Consulta
Scopes i permisos.
Quan, si i fes
Una regla té exactament tres peces mòbils:
| Peça | Camp | Què decideix |
|---|---|---|
| Quan | trigger_type | L'esdeveniment que escolta la regla, en forma resource.action (invoice.paid) |
| Si | conditions | Un arbre de condicions sobre els camps d'aquell esdeveniment. Un {} buit vol dir sense condició: la regla actua sempre |
| Fes | actions | Les accions que s'executen quan un esdeveniment coincideix, en l'ordre en què les declaris |
Pregunta al catàleg en comptes d'endevinar. GET /v1/automations/catalog retorna
els activadors als quals la teva empresa es pot subscriure —ja filtrats pels
mòduls que inclou el teu pla, de manera que un activador governat per un mòdul
que no has contractat ni s'ofereix—, més el conjunt tancat d'operadors i
combinadors que admet una condició i les accions amb adaptador registrat en aquest
desplegament. És determinista: dues crides seguides sense canvis de configuració
retornen el mateix cos, així que desa'l a la memòria cau i compara'l.
Els camps avaluables d'un activador són una segona crida. Són fora del
catàleg expressament: al voltant d'un centenar d'activadors visibles amb desenes
de propietats cadascun donarien un document de centenars de kilobytes per acabar
fent servir els camps d'un. Demana
GET /v1/automations/catalog/triggers/{trigger}/fields
per a l'activador que hagis triat, i construeix la condició contra els camps que
enumeri.
Avui existeixen vuit tipus d'acció: notify_in_app, notify_channel,
emit_webhook, create_calendar_event, send_document_email,
send_payment_reminder, change_status i tag_entity. El catàleg anuncia només
els que tenen adaptador cablejat, mai la llista de tipus declarats — triar un
tipus sense adaptador produiria una regla el pas de la qual s'omet en executar-se.
Una regla neix inactiva. Crear-la segella la versió 1 i la deixa en draft:
no escolta res fins que l'actives amb
POST /v1/automations/rules/{rule}/activate.
L'activació no comprova per endavant el teu pressupost mensual, i és expressament
així — llegeix abans
l'endpoint de consum
si vols anticipar-t'hi.
curl -X POST https://api.factuarea.com/v1/automations/rules \
-H "Authorization: Bearer $FACTUAREA_API_KEY" \
-H "Content-Type: application/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"
}
}
]
}'Cada edició segella una versió
Editar una regla mai reescriu la seva definició anterior. Segella una versió
nova i puja current_version, i cada execució conserva un punter a la versió
exacta que va executar, així que una execució de fa setmanes es continua llegint
després que la regla hagi avançat.
PUT /v1/automations/rules/{rule}actualitza de manera parcial: els camps que ometis conserven el seu valor, i""adescriptionel buida. L'estat queda intacte — editar una regla activa la deixa activa, executant la versió nova des del seu esdeveniment següent.- Pausar i activar no toquen la definició, així que no segellen cap versió.
GET /v1/automations/rules/{rule}/versionsllista les versions segellades i.../versions/{version}en retorna una, amb l'arbre de condicions i les accions congelats tal com eren.
El rule_version d'una execució apunta exactament a aquell número. Pot quedar
per darrere de current_version, i aquesta és la gràcia.
L'assaig no materialitza res
POST /v1/automations/rules/{rule}/dry_run
respon què faria una regla davant d'un esdeveniment d'exemple. No executa
res: no surt cap correu, no es crea cap entrega de webhook, no es muta cap
entitat, no s'escriu cap fila d'execució ni de pas, i no consumeix ni el
pressupost mensual ni el límit de freqüència del motor. Per això demana l'scope
de lectura tot i ser un POST — l'esdeveniment d'exemple ha de viatjar al cos.
La resposta porta matched, una entrada de condition_trace per cada fulla
avaluada en ordre d'avaluació, i una entrada de steps per acció amb allò que
resoldria. Una condició que no es pot avaluar torna com a condition_error amb
un 200, no com una fallada HTTP: veure per què una regla no es pot avaluar
abans d'activar-la és justament per a això que serveix l'assaig.
Si la regla actua sobre documents — enviar un document per correu, enviar un
recordatori de cobrament, canviar un estat, etiquetar una entitat — passa
event_aggregate_id amb l'id d'un document real teu. Sense ell, l'assaig
informa que no s'executaria cap pas, i una regla perfectament correcta sembla
trencada.
curl -X POST https://api.factuarea.com/v1/automations/rules/{rule}/dry_run \
-H "Authorization: Bearer $FACTUAREA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"event_type": "invoice.paid",
"event_payload": { "total": 1200, "status": "paid" }
}'Execucions i els seus passos
Cada esdeveniment admès produeix una execució, i cada acció de la definició
congelada produeix un pas. Una execució porta la definició que va executar
(rule_version + rule_snapshot) i el payload de l'esdeveniment que la va
disparar (event_payload), tots dos congelats en el moment d'executar.
| Estat de l'execució | Què vol dir |
|---|---|
pending | En cua, sense començar |
running | En curs |
completed | Tots els passos van aplicar el seu efecte |
failed | Va acabar sense produir el seu efecte, i no es pot reprocessar |
dead_lettered | Aparcada, a l'espera d'un rellançament manual |
blocked | Aturada per un límit del motor abans d'executar-se |
Els passos tornen sempre en ordre d'execució, perquè step_index —començant
per zero— és la identitat del pas: és allò que es rellança i allò que
l'esdeveniment automation_run.step_dead_lettered publica com a
data.step_index. Cada pas porta el seu action_type, els seus parameters
congelats, el result que va tornar el seu adaptador i una marca replayable.
Dos eixos ortogonals expliquen un desenllaç. discard_reason és el motiu de
descart classificat, d'un catàleg tancat —condition_not_matched,
chain_depth_exceeded, rate_limit_exceeded, monthly_budget_exhausted,
step_attempts_exhausted…—, així que ramifica segons ell. last_error és el
missatge tècnic cru, pensat per depurar. discard_reason_label és l'etiqueta
humana del motiu i va sempre en castellà: pertany al vocabulari del motor i
no segueix Accept-Language.
Llegeix l'historial amb
GET /v1/automations/runs
—filtra per automation_rule_id, status o una finestra created[…]—,
GET /v1/automations/runs/{run}
i GET /v1/automations/runs/{run}/steps. Tots tres paginen per cursor; consulta
Paginació.
Rellançar torna a executar la feina de debò
Dues operacions rearmen feina aparcada: POST /v1/automations/runs/{run}/replay
rearma tots els passos aparcats d'una execució, i
POST /v1/automations/runs/{run}/steps/{step_index}/replay
en rearma un de sol, deixant els seus germans amb el seu estat, el seu motiu i
les seves marques de temps intactes.
Els passos rearmats s'executen de debò: envien correu, entreguen webhooks i criden tercers. Això no és un reintent inert — confirma-ho amb el titular del compte abans de cridar-ho.
- Només es rearmen els passos aparcats amb un motiu rellançable. Una execució
encara en curs, o una que va acabar netament, es rebutja amb un 422
automation_replay_not_allowed. - La resposta és un 202 —acceptat i encuat, no acabat— i el seu cos porta
només identificadors, deliberadament sense
status, perquè «encuat» no és cap dels estats de l'execució. Comprova el desenllaç amb l'execució, o més barat amb els seus passos. - Cridar-ho dues vegades no duplica l'efecte: el motor revisa de nou l'estat de cada pas dins del seu propi bloqueig.
step_indexés l'índex que publica l'endpoint de passos, no la posició de l'acció a la definició de la regla. Un índex fora de rang retorna un 404, igual que una execució que no és teva.
Els límits del motor
Quatre límits del motor acoten allò que farà en nom teu. Una execució aturada per
qualsevol d'ells queda registrada com a blocked amb el seu motiu tipat —
bloquejada no és fallida, i llegir el motiu les distingeix.
| Límit | Què acota | Motiu i codi d'error |
|---|---|---|
| Profunditat d'encadenament | Salts «acció → esdeveniment → regla», tres per defecte | chain_depth_exceeded · 422 automation_chain_depth_exceeded |
| Límit de freqüència | Execucions admeses per minut i empresa. Un fre de pic, no de volum | rate_limit_exceeded · 429 automation_rate_limit_exceeded |
| Pressupost mensual | Execucions que permet el pla per període | monthly_budget_exhausted · 402 automation_monthly_budget_exhausted |
| Fallades consecutives | Una ratxa d'execucions fallides pausa la regla sola | Esdeveniment automation_rule.auto_paused amb consecutive_failures |
Un esdeveniment que produeix una persona o una integració entra amb profunditat
zero, així que només consumeix el pressupost d'encadenament allò que va provocar
una automatització. Una regla que reacciona a automation_run.failed i torna a
fallar no pot, per tant, repetir-se sense fi.
GET /v1/automations/usage és on veus com vas davant del pressupost mensual:
consumed, limit (null vol dir sense límit, mai «desconegut» — tracta'l
com que no hi ha barra de progrés, no com a zero), reset_at ja resolt, el
period en format YYYY-MM i el threshold_percent a partir del qual la
plataforma avisa el titular del compte. Aquell percentatge viatja perquè el teu
avís i el nostre no es desalineïn.
Un pas concret també té límit d'intents. Quan s'exhaureix, el pas queda aparcat
com a dead_lettered amb step_attempts_exhausted i espera un rellançament — és
l'únic estat que admet reentrada.
Regles de cartera per a gestories
Una regla declara quines empreses vigila al seu camp opcional scope:
empresa —el valor que pren si l'omets— vigila els esdeveniments de l'empresa
que la posseeix, i cartera vigila els esdeveniments de totes les empreses
gestionades per una gestoria, entregant-li l'avís a ella.
L'abast és immutable. El tries en crear la regla, i per canviar-lo crees una
altra regla. Una edició que enviï un valor diferent es rebutja amb
automation_rule_scope_immutable:
envia l'abast que la regla ja té, o omet el camp.
cartera requereix el mòdul de gestoria i una empresa que no estigui al seu torn
gestionada per una altra. El catàleg retorna sempre els dos abasts, cadascun
amb available i, quan no ho està, un unavailable_reason: module_not_granted
(ampliar el pla el concedeix) o company_is_managed_child (la jerarquia té un sol
nivell, així que cap pla el desbloqueja). Així distingeixes «no contractat» de «no
existeix». Crear una regla de cartera sense aquell dret retorna un 403
automation_portfolio_scope_not_available.
En cartera només s'admeten quatre dels vuit tipus d'acció: els que avisen.
notify_in_app, notify_channel, emit_webhook i create_calendar_event
avisen la gestoria o no toquen cap entitat. Els altres quatre
—send_document_email, send_payment_reminder, change_status i tag_entity—
tindrien per subjecte un document de l'empresa gestionada, cosa que la frontera
multiempresa no permet. Es rebutgen en crear o editar la regla, mai en
executar-la, amb un 422
automation_portfolio_scope_forbids_action.
Cada acció del catàleg porta supports_portfolio_scope perquè filtris abans
d'escriure la regla.
Una execució de cartera es desa sota la gestoria i anomena a subject_company
l'empresa gestionada sobre la qual va actuar, que és null a les execucions
d'abast empresa. El bloc viatja fins i tot quan aquella empresa ja no es pot
llegir: id i name tornen a null en comptes de desaparèixer el bloc. Filtra
execucions amb GET /v1/automations/runs?subject_company_id=… i regles amb
GET /v1/automations/rules?scope=cartera.
En mode de prova res no surt del sandbox
Una clau fact_test_ opera contra una empresa sandbox aïllada, i allà el motor es
comporta igual fins a l'últim instant: l'activador coincideix, l'execució s'admet
i es registra, i cada pas queda neutralitzat just abans de produir el seu
efecte. El pas tanca amb sandbox_neutralized i l'execució acaba completed —
un efecte neutralitzat és el desenllaç buscat, no una fallada. No s'envia cap
correu, no s'entrega cap webhook i cap document no canvia. Consulta
Mode de prova i sandbox.
Passos següents
els set esdeveniments de cicle de vida que emet el motor, i per què ells mateixos són activadors vàlids.
la mateixa superfície com a tools per a un agent.
el cicle de vida complet des del terminal.
tots els codis que emet el motor, amb la seva causa i què fer.
Referència API.
Referència API.
Referència API.