Factuarea APIDevelopers

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çaCampQuè decideix
Quantrigger_typeL'esdeveniment que escolta la regla, en forma resource.action (invoice.paid)
SiconditionsUn arbre de condicions sobre els camps d'aquell esdeveniment. Un {} buit vol dir sense condició: la regla actua sempre
FesactionsLes 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 "" a description el 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}/versions llista 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
pendingEn cua, sense començar
runningEn curs
completedTots els passos van aplicar el seu efecte
failedVa acabar sense produir el seu efecte, i no es pot reprocessar
dead_letteredAparcada, a l'espera d'un rellançament manual
blockedAturada 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ímitQuè acotaMotiu i codi d'error
Profunditat d'encadenamentSalts «acció → esdeveniment → regla», tres per defectechain_depth_exceeded · 422 automation_chain_depth_exceeded
Límit de freqüènciaExecucions admeses per minut i empresa. Un fre de pic, no de volumrate_limit_exceeded · 429 automation_rate_limit_exceeded
Pressupost mensualExecucions que permet el pla per períodemonthly_budget_exhausted · 402 automation_monthly_budget_exhausted
Fallades consecutivesUna ratxa d'execucions fallides pausa la regla solaEsdeveniment 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

En aquesta pàgina

Et donem un cop de mà?Contactar amb suport