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 d'un compte.
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/companies/{company}/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/companies/{company}/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/companies/{company}/automations/catalog/triggers/{trigger}/fields
per a l'activador que hagis triat, i construeix la condició contra els camps que
enumeri.
Avui existeixen dotze tipus d'acció: notify_in_app, notify_channel,
emit_webhook, create_calendar_event, send_document_email,
send_payment_reminder, change_status, tag_entity i, per a tasques,
create_task, change_task_status, assign_task i add_task_comment: consulta
Tasques i projectes. 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.
create_calendar_event està retirada: el calendari al qual alimentava ja no
existeix, així que el nom es queda al vocabulari —una versió segellada abans
continua llegint-se—, però cap adaptador no l'executa i el seu pas no produeix
cap efecte. Fes servir create_task en el seu lloc.
L'enumerat type d'una acció ha crescut. Si la teva integració valida
actions[].type contra una llista tancada, afegeix create_task,
change_task_status, assign_task i add_task_comment, i continua
reconeixent create_calendar_event perquè les versions antigues de les regles
continuïn llegint-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/companies/{company}/automations/rules/{rule}/activate.
L'activació comprova el límit d'automatitzacions actives del pla. No comprova
per endavant el pressupost mensual d'execucions: es comprova en admetre una
execució. Llegeix
l'endpoint de consum
per consultar tots dos comptadors abans d'activar.
curl -X POST https://api.factuarea.com/v1/companies/{company}/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"
}
}
]
}'Tasques i projectes
Les automatitzacions arriben al mòdul de tasques en els dos
sentits: els seus esdeveniments posen en marxa regles, i quatre accions creen i
canvien tasques. Tots dos necessiten el mòdul tasks.
Activadors
Els 21 esdeveniments de tasques i projectes
—task.*, task_comment.*, task_time_entry.* i project.*— són activadors
vàlids. Com tot activador governat per un mòdul, existeixen només per a una
empresa amb el mòdul tasks: si no, el catàleg no els ofereix i desar una regla
que en faci servir un retorna 422. Les condicions llegeixen els camps que publica
cada esdeveniment —en una tasca, entre d'altres, el seu estat, columna,
prioritat, projecte, persona assignada, data de venciment i data de
completat; consulta'ls amb
GET /v1/companies/{company}/automations/catalog/triggers/{trigger}/fields—
i l'execució congela com a payload el data.object de l'esdeveniment.
Accions
| Acció | Què fa | Paràmetres |
|---|---|---|
create_task | Crea una tasca | project_id (obligatori: un projecte actiu de la teva empresa), title (obligatori, fins a 500 caràcters), description (Markdown), priority, assignee_mode (user, role o trigger_actor) amb assignee_user_id o assignee_role (owner, admin o member), label_ids, la data de venciment i link_to_trigger |
change_task_status | Mou la tasca de l'activador | target: l'id d'una columna del projecte de la tasca, o planned o archived |
assign_task | Assigna la tasca de l'activador | assignee_user_id: un membre de la teva empresa |
add_task_comment | Comenta la tasca de l'activador | body: Markdown, d'1 a 10.000 caràcters |
{
"name": "Follow up approved quotes",
"scope": "empresa",
"trigger_type": "quote.approved",
"conditions": {},
"actions": [
{
"type": "create_task",
"order": 0,
"parameters": {
"project_id": "0193a4f2-7c20-7a11-8b52-4d6e8f0a2c01",
"title": "Prepare the delivery of the approved quote",
"priority": "high",
"assignee_mode": "role",
"assignee_role": "admin",
"link_to_trigger": true
}
}
]
}- La tasca de l'activador. Les tres últimes accions hi actuen: la pròpia
tasca als esdeveniments
task.*, i la tasca a la qual pertany un comentari o una imputació de temps als esdevenimentstask_comment.*itask_time_entry.*. Amb qualsevol altre activador, o si la tasca ja no existeix, el pas es descarta ambtask_target_not_found. - Data de venciment de
create_task. Enviadue_on(una data explícita) odue_from_payload_pathambdue_offset_days(un camp de data del payload congelat més un nombre de dies), mai les dues. Un camp que falta o que no és una data fa fallar el pas amb un missatge que el nomena: no s'inventa cap data. Sense cap de les dues, la tasca no té data de venciment. link_to_triggervincula la tasca nova amb l'entitat que ha disparat la regla —una factura, un pressupost, un contacte…—, de manera que apareix entre les tasques vinculades d'aquesta entitat. Si l'activador no té una entitat vinculable, la tasca es crea sense vincle i la traça del pas ho indica.- Persona assignada.
assignee_mode: "trigger_actor"assigna l'usuari que ha causat l'esdeveniment, i deixa la tasca sense assignar quan l'esdeveniment no identifica cap membre.roletria el primer usuari de l'empresa amb aquest rol, en un ordre determinista. Un usuari que no és membre de l'empresa fa fallar el pas i no crea res. - Els comentaris d'una automatització no tenen un usuari com a autoria (el seu
author.typeésautomation); ningú els pot editar i un admin els pot esborrar. - Les referències es comproven contra la teva empresa —el projecte, la persona
assignada, les etiquetes i un
targetque sigui una columna— en desar la regla (422, amb el mateix missatge tant si la referència és d'una altra empresa com si no existeix) i de nou en executar-la. - Passos descartats. Un
create_taskel projecte del qual es va arxivar després de desar la regla es descarta ambtask_project_not_foundi es pot rellançar quan el desarxivis; una empresa que ha perdut el mòdultasksrepmodule_not_accessible, rellançable quan el mòdul torni. - Els bucles es tallen. Una regla
task.created→create_taskarriba al límit de profunditat de cadena com qualsevol altra cadena. - L'assaig valida paràmetres, referències, subjecte i mòdul exactament igual que una execució real, i no crea cap tasca ni cap comentari.
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.
PATCH /v1/companies/{company}/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/companies/{company}/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/companies/{company}/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/companies/{company}/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/companies/{company}/automations/runs
—filtra per automation_rule_id, status o una finestra created[…]—,
GET /v1/companies/{company}/automations/runs/{run}
i GET /v1/companies/{company}/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/companies/{company}/automations/runs/{run}/replay
rearma tots els passos aparcats d'una execució, i
POST /v1/companies/{company}/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
El pla acota quantes regles pots activar. Per separat, quatre límits acoten
les execucions: una execució aturada per un d'ells queda registrada com a
blocked amb el seu motiu tipat — bloquejada no és fallida, i llegir el motiu
les distingeix. El rebuig pel límit d'actives no crea una execució.
| Límit | Què acota | Motiu i codi d'error |
|---|---|---|
| Automatitzacions actives | Regles actives i no eliminades de la teva empresa; es comprova en activar o reprendre | Activació rebutjada · 402 automation_active_rules_limit_exceeded |
| 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/companies/{company}/automations/usage és on veus com vas davant del pressupost mensual:
consumed, limit (null vol dir sense sostre automàtic, 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.
La mateixa resposta també inclou active_rules: {count, limit}: count és
el nombre de regles actives i no eliminades de l'empresa; els esborranys i les
pausades no compten. limit és el límit del pla, inclòs zero quan no es permet
activar, o null quan no hi ha un sostre automàtic. La capacitat d'Enterprise
s'acorda segons contracte. La resposta pública v1 i MCP get_automation_usage
exposen el mateix parell, sense limit_mode.
Fragment de la resposta:
{
"data": {
"active_rules": { "count": 7, "limit": 7 }
}
}Quan count >= limit amb un límit fix, activar o reprendre una regla es rebutja
amb automation_active_rules_limit_exceeded: v1 retorna 402 amb
error.type: payment_required_error i error.details: {active_rules, limit}.
Pausa una regla activa amb POST /v1/companies/{company}/automations/rules/{rule}/pause o amplia el
pla abans de tornar-ho a intentar. MCP activate_automation_rule retorna
JSON-RPC -32008, amb el mateix codi a data.code, data.http_status: 402 i el
mateix parell a data.details; l'app respon HTTP 422 amb el mateix codi.
Les regles ja actives per sobre del límit es continuen executant i es poden editar o pausar. Aquest límit no les pausa automàticament; només impedeix noves activacions. Pausar allibera una plaça d'actives, i reprendre torna a comprovar el límit. El pressupost mensual d'execucions continua separat i es comprova en executar.
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
Una regla declara quins NIF 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 la cartera del compte que la
posseeix, i n'entrega l'avís a aquella empresa, el NIF titular del compte. Es van
dissenyar per a les gestories, que són comptes com qualsevol altre.
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.
Què vigila una regla de cartera. Els altres NIF reals del compte, més els
NIF que un altre compte posa al seu abast per una relació vigent amb nivell
operate, un accés cedit o un
compte gestionat. Una relació amb nivell view, o una
que es va revocar o ha acabat, no aporta res. La regla mai no vigila l'empresa que
la posseeix: si vols la mateixa automatització per a aquella empresa, crea-la amb
abast empresa.
L'univers no és una llista desada. Es calcula a partir de cada esdeveniment i es
torna a comprovar a cada pas: en triar les regles candidates d'un esdeveniment,
abans d'escriure l'execució, dins de cada pas abans que s'executi la seva acció, i
quan rellances una execució o un pas. Un NIF que s'ha arxivat, desactivat o
traspassat a un altre compte, o la relació del qual es va revocar, va acabar o va
baixar a view, no passa la comprovació: no s'escriu cap execució per a ell o, si
l'execució ja existeix, el pas s'atura com a blocked amb el motiu
tenant_mismatch i la seva acció no s'executa mai. Rellançar no l'esquiva.
Qui pot crear una regla de cartera. Només l'empresa titular d'un compte que
tingui concedit el mòdul gestoria, per pla (empresario i enterprise) o per
un override d'empresa. El primer que es pregunta és si l'empresa és la titular del
seu compte: un NIF addicional —un que el compte va comprar, va rebre per traspàs o
va donar d'alta— mai no té cartera pròpia, encara que se li hagi concedit el
mòdul, perquè la cartera és del compte i la representa el seu titular. No
necessites un segon NIF per escriure la regla; mentre el compte no en tingui,
simplement no es dispara.
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 (l'empresa no és la titular del seu
compte, així que cap pla ho desbloqueja; el nom és heretat i es conserva perquè
forma part del contracte). 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 cinc dels dotze tipus d'acció.
notify_in_app, notify_channel i emit_webhook avisen l'empresa titular o no toquen
cap entitat, i create_task crea la tasca en un projecte de la pròpia
empresa titular —link_to_trigger es rebutja a cartera, perquè l'entitat que ha
disparat la regla és d'un altre NIF—. La retirada create_calendar_event
conserva el seu lloc en aquest grup però no fa res. Els altres set
—send_document_email, send_payment_reminder, change_status, tag_entity,
change_task_status, assign_task i add_task_comment— tindrien per subjecte un
document o una tasca d'un altre NIF, 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.
De qui és l'execució i quin és el seu subjecte. Una execució de cartera es
desa sota l'empresa titular del compte: és la seva regla, els seus avisos
arriben a la seva bústia i les seves execucions consumeixen el seu pressupost
mensual i el seu límit de freqüència, així que el pressupost es gasta en
proporció a la cartera. Un esdeveniment pot iniciar més d'una execució quan el seu
NIF és a la cartera de més d'un titular, per exemple un NIF cedit a un altre
compte amb nivell operate: cada titular amb una regla que coincideixi té la
seva pròpia execució, contra el seu propi pressupost. Cada execució anomena a
subject_company el NIF sobre el qual va actuar, que és null a les execucions
d'abast empresa. El bloc viatja fins i tot quan aquell NIF ja no es pot llegir:
id i name tornen a null en comptes de desaparèixer el bloc. El propi NIF no
veu les execucions de cartera del seu titular: són del titular i porten la
definició congelada de la seva regla.
Filtra execucions amb
GET /v1/companies/{company}/automations/runs?subject_company_id=… i regles amb
GET /v1/companies/{company}/automations/rules?scope=cartera. Filtrar per un NIF
fora de la cartera retorna una pàgina buida, mai un error, així que el filtre no
serveix per esbrinar quins NIF existeixen.
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.