LimitRail - guida di configurazione e integrazione
Questa guida spiega come configurare LimitRail e come integrarlo da un sistema esterno. È pensata per due lettori:
- chi configura prodotti, operazioni, fee e limiti nel backoffice;
- chi integra le API pubbliche da un core, da una piattaforma di integrazione o da un canale digitale.
LimitRail non autorizza direttamente il movimento di denaro e non possiede il saldo del conto. LimitRail decide la policy: calcola fee, verifica limiti, riserva capacità e produce evidenza leggibile. Il sistema chiamante resta responsabile dell'esecuzione dell'operazione finanziaria.
Vai subito alla guida operativa: Appendice A - Playbook operativo di configurazione e integrazione.
1. Che cosa fa LimitRail
LimitRail è un motore di policy, pricing e limiti. Il sistema chiamante invia:
- account esterno;
- codice operazione;
- importo e valuta, se richiesti;
- metadata runtime, se la policy dipende da informazioni dell'operazione;
- modalità di valutazione: solo preview, riserva capacità o commit immediato.
LimitRail restituisce:
- decisione di policy:
ALLOWED,DENIED_BY_POLICY,WARNING,FEE_CALCULATED; - fee calcolate;
- limiti e contatori impattati;
- policy risolta e provenienza;
- dimensioni usate, mancanti o non usate;
- eventuale reservation id da confermare o cancellare.
%%{init: {"theme": "base", "themeVariables": {"background": "#ffffff", "mainBkg": "#ffffff", "primaryColor": "#f8fafc", "primaryTextColor": "#0f172a", "primaryBorderColor": "#475569", "lineColor": "#1d4ed8", "textColor": "#0f172a"}}}%%
flowchart LR
BO[Backoffice LimitRail] --> CFG[Product, operations, dimensions, condition plan]
CFG --> PUB[Published policy version]
INT[Core / sistema integratore] --> API[LimitRail public API]
PUB --> API
API --> OUT[Decisione, fee, contatori, spiegazione]
OUT --> INT
2. Configurazione backoffice
2.1 Product
Il product rappresenta il tipo di prodotto commerciale, ad esempio un conto standard, business o premium.
| Campo | Esempio | Perché è importante |
|---|---|---|
code |
STD_ACCOUNT |
È il codice stabile usato nelle integrazioni e nelle policy. |
name |
Account Standard |
È il nome leggibile per operatori e demo. |
currencyCode |
EUR |
È la valuta base usata quando la richiesta runtime non specifica una valuta. |
status |
ACTIVE |
Solo prodotti attivi devono essere usati in runtime. |
defaultConditionPlanId |
... |
Collega il prodotto al pacchetto di pricing e limiti. |
Regola pratica: il product code è un contratto tecnico. Non deve essere rinominato liberamente dopo che un integratore lo usa.
2.2 Operation catalog
Una operation è il codice operativo ricevuto dal sistema chiamante. Se il core invia A14, LimitRail deve conoscere A14. Non serve un mapping aggiuntivo quando il codice ricevuto è già il codice canonico condiviso.
| Campo | Esempio | Effetto runtime |
|---|---|---|
code |
A14 |
Codice che arriva in operationCode nella chiamata runtime. |
name |
International wire transfer |
Testo leggibile per UI, audit e documentazione. |
familyCode |
TRANSFER |
Raggruppa operazioni simili. |
channelCode |
WIRE_TRANSFER |
Alimenta la system dimension channel. |
requiresAmount |
true |
Se manca amount, la chiamata runtime viene rifiutata. |
requiresPricingCoverage |
true |
La readiness segnala se manca pricing. |
requiresLimitCoverage |
true |
La readiness segnala se manca un limite. |
Esempio:
{
"code": "A14",
"name": "International wire transfer",
"familyCode": "TRANSFER",
"channelCode": "WIRE_TRANSFER",
"requiresAmount": true,
"requiresPricingCoverage": true,
"requiresLimitCoverage": true
}
2.3 Policy dimensions
Le policy dimensions sono il vocabolario controllato delle informazioni che il motore può usare per decidere. Non sono semplici note libere e non sono campi messi lì per descrivere una transazione. Una dimensione risponde a una domanda precisa: "questo dato può cambiare una fee, un limite, un contatore o una spiegazione audit?"
Esempi di domande di business che diventano dimensions:
- Il bonifico va verso un paese domestico o estero?
- Il cliente è retail, business, VIP o dipendente?
- L'operazione arriva da mobile, filiale, API o batch?
- Il pagamento è istantaneo?
- Il cliente è residente o non residente?
- Questa informazione deve separare i limiti oppure serve solo per scegliere quale regola applicare?
| Campo | Significato |
|---|---|
code |
Nome tecnico della dimensione. Viene normalizzato in minuscolo nel runtime context. |
displayName |
Nome leggibile. |
dataType |
STRING, DECIMAL, INTEGER, BOOLEAN, DATE, ENUM. |
source |
Da dove arriva il valore: REQUEST_METADATA, ACCOUNT_ATTRIBUTE, SYSTEM. |
allowedValues |
Lista opzionale di valori ammessi. Serve quando il dato deve essere controllato, per esempio solo ITA, FRA, DEU, ESP, USA come paesi supportati. Se arriva XXX, LimitRail rifiuta la richiesta invece di applicare una regola sbagliata. |
isRuleEnabled |
Indica se questa informazione può essere usata per far scattare o non far scattare una regola di pricing o limite. Esempio: se wire_country_destination = FRA, applica fee internazionale; se customer_tier = GOLD, applica fee ridotta. |
canUseInCounterScopes |
Indica se questa informazione può entrare nella chiave del limite, cioè nel modo in cui LimitRail accumula i consumi. Esempio: un limite giornaliero può essere unico per tutti i bonifici, oppure può avere un contenitore diverso per ogni paese destinazione. Se abiliti questa opzione per wire_country_destination, il consumo verso FRA può essere contato in un contenitore diverso dal consumo verso USA. |
isSensitive |
Indica se il valore deve essere nascosto nelle risposte e nei log leggibili. Esempio: una dimensione di rischio può influenzare la policy, ma non deve apparire in usedDimensions se è sensibile. |
2.3.1 Come leggere questi campi senza tecnicismi
allowedValues: controllare che l'integratore mandi valori corretti
Usalo quando vuoi impedire valori non previsti. Per esempio, se la dimensione wire_country_destination accetta solo ITA, FRA, DEU, ESP, USA, allora una richiesta con wire_country_destination = "BR" viene rifiutata se BR non è configurato. Questo evita che una transazione venga trattata come "caso generico" quando invece il prodotto non ha regole per quel valore.
Esempio pratico:
{
"metadata": {
"wire_country_destination": "FRA"
}
}
Se FRA è tra i valori ammessi, la valutazione continua. Se arriva UNKNOWN_COUNTRY, il runtime risponde con errore funzionale.
isRuleEnabled: usare il dato per scegliere quale regola applicare
Questa opzione significa: "le regole possono leggere questa informazione". Una regola di pricing o limite può avere una condizione del tipo:
- applica questa fee solo se
wire_country_destinationè diverso daITA; - applica questo limite solo se
customer_tierèBASIC; - non applicare questa fee se
employee = true; - blocca l'operazione se
risk_segment = HIGHe l'importo supera una soglia.
In altre parole, isRuleEnabled decide se la dimensione può entrare nella logica decisionale. Non abilitarlo per campi che vuoi solo conservare o mostrare, ma che non devono cambiare la decisione.
Esempio di logica:
| Dato ricevuto | Regola configurata | Risultato |
|---|---|---|
wire_country_destination = ITA |
fee internazionale solo se paese diverso da ITA |
fee internazionale non applicata |
wire_country_destination = FRA |
fee internazionale solo se paese diverso da ITA |
fee internazionale applicata |
customer_tier = GOLD |
fee ridotta per clienti GOLD | fee ridotta applicata |
employee = true |
fee azzerata per dipendenti | fee azzerata |
canUseInCounterScopes: usare il dato per separare il consumo dei limiti
Questa opzione non decide se la regola vale. Decide come viene contato il consumo.
Esempio 1: limite unico per operazione.
- Regola: massimo 10.000 EUR al giorno per bonifici
A14. - Scope: account + operation.
- Risultato: tutti i bonifici
A14dello stesso account consumano lo stesso limite giornaliero.
Esempio 2: limite separato per paese destinazione.
- Regola: massimo 10.000 EUR al giorno per bonifici
A14, separato perwire_country_destination. - Scope: account + operation +
wire_country_destination. - Risultato: 6.000 EUR verso
FRAe 6.000 EUR versoUSAfiniscono in due contatori diversi.
Questa scelta è potente ma va usata con attenzione. Non usare mai valori troppo variabili, come transaction id, descrizione libera o riferimento operazione, per separare i contatori: genererebbero troppi contatori e peggiorerebbero costo e performance.
isSensitive: usare il dato senza mostrarlo
Una dimensione sensibile può influenzare la policy ma non deve essere mostrata nella risposta leggibile. Esempio: risk_segment = HIGH può bloccare o irrigidire un limite, ma potresti non volerlo esporre al chiamante o in schermate operative non autorizzate.
2.4 Tre tipi di dimensioni
System dimensions
Sono calcolate dal runtime, non vanno inviate nei metadata:
| Dimensione | Valore |
|---|---|
operation |
operation code risolto, per esempio A14. |
channel |
channel code dell'operazione, per esempio WIRE_TRANSFER. |
segment |
segment code dell'account, se presente. |
product |
product code dell'account. |
currency |
valuta richiesta o valuta account. |
Request metadata
Sono valori che cambiano per singola operazione. Si inviano dentro metadata nella chiamata runtime o nel commit.
Esempi:
wire_country_destination = "ITA": destinazione del bonifico;beneficiary_bank_country = "DEU": paese banca beneficiaria;channel_risk_score = 72: score calcolato dal canale;is_instant = true: flag bonifico istantaneo.
Usali quando la decisione dipende dalla transazione specifica.
Account attributes
Sono valori stabili dell'account. Si salvano sull'account contract o tramite API account attributes.
Esempi:
customer_tier = "GOLD";residency = "IT";risk_segment = "LOW";employee = true.
Usali quando la decisione dipende dal profilo dell'account, non dalla singola transazione.
2.5 Esempio: perché i metadata contano
Scenario: i bonifici internazionali verso paesi non domestici costano di più e hanno un limite giornaliero separato per paese destinazione.
Configurazione:
- dimensione
wire_country_destination, sourceREQUEST_METADATA, typeENUM; - allowed values:
ITA,FRA,DEU,ESP,USA; - pricing rule: se
wire_country_destination != "ITA", applica fee internazionale. In parole semplici: il paese destinazione decide quale fee usare; - limit rule: perimetro del contatore custom con
wire_country_destination. In parole semplici: il paese destinazione decide anche dove accumulare il consumo del limite.
Runtime request payload:
{
"externalAccountRef": "000100000203",
"operationCode": "A14",
"amount": 2500.00,
"currencyCode": "EUR",
"externalOperationRef": "wire-2026-000001",
"occurredAtUtc": "2026-06-13T10:15:00Z",
"metadata": {
"wire_country_destination": "FRA"
},
"mode": "PREVIEW"
}
Effetto nel motore:
operation,channel,product,currencyvengono aggiunte automaticamente;wire_country_destinationviene validata contro il registry;- le condizioni delle regole che leggono
wire_country_destinationpossono attivare o escludere pricing e limiti; - se la dimensione è parte del perimetro del contatore, il contatore non sarà solo
account + operation, ma anchewire_country_destination; - la risposta indicherà la dimensione in
usedDimensionsse non è sensibile.
2.6 Scenari di limiti e fee su un conto di pagamento
Questa sezione usa esempi generici per mostrare come trasformare requisiti di prodotto in configurazione LimitRail. Lo scopo non è copiare un catalogo operativo specifico, ma far capire quali dati devono diventare operation, quali devono diventare dimensioni e quali regole sono applicabili dal motore.
2.6.1 Che cosa è applicabile oggi e che cosa richiede dati esterni
| Requisito di prodotto | Applicabilità in LimitRail | Come configurarlo |
|---|---|---|
| Fee fissa per una operazione, per esempio 0,35 EUR su un servizio specifico | Applicabile oggi | Pricing rule FIXED sull'operation code. |
| Operazione gratuita | Applicabile oggi | Pricing rule WAIVER, oppure nessuna pricing rule se non vuoi mostrare una fee a zero. Usa WAIVER quando vuoi rendere esplicito che quella operazione è inclusa. |
| Limite mensile di volume, per esempio 2.400 EUR al mese per account | Applicabile oggi | Limit rule AMOUNT, MONTHLY, blocking, con counter scope ACCOUNT_GLOBAL, ACCOUNT_CHANNEL o ACCOUNT_OPERATION in base al perimetro desiderato. |
| Limite annuale sul numero di operazioni incluse, poi fee | Applicabile oggi quando la quota è per singolo operation code | Pricing rule TIERED, metrica COUNT, periodo YEARLY, tiers con primo scaglione a fee zero e scaglione successivo a fee piena. |
| Quota annuale condivisa fra più operation code diversi | Applicabile se modellata con un unico operation code canonico | Oggi il tiered pricing accumula per account + operation. Se la quota deve essere unica su più varianti, usa un unico operation code e una dimensione per distinguere il dettaglio. Se mantieni codici separati, la quota resta separata per codice. |
| Fee basata sull'importo della singola operazione, per esempio gratuita fino a 35 EUR e poi 0,30 EUR | Applicabile se il sistema chiamante invia una fascia importo come metadata | Oggi le condizioni leggono dimensioni governate, non direttamente l'amount come campo di condizione. Configura una dimensione amount_band e fai calcolare al chiamante UP_TO_35 o ABOVE_35. |
| Fee mensile basata su saldo medio | Applicabile solo se il saldo medio arriva da fuori | LimitRail non calcola saldi medi. Il sistema contabile calcola average_monthly_balance e lo invia come metadata della fee mensile o lo salva come account attribute. |
| Saldo massimo conto, per esempio 3.600 EUR | Applicabile solo se il sistema chiamante fornisce il saldo proiettato | LimitRail non possiede il saldo. Il chiamante deve inviare projected_balance_after_operation; LimitRail può bloccare quando quel valore supera la soglia. |
| Eccezione temporanea su una singola operazione | Applicabile come dato esplicito, non come processo operativo completo | Il chiamante può inviare limit_exception_granted = true o usare un account override temporaneo. Il processo di approvazione resta nel sistema operativo che governa ruoli e autorizzazioni. |
2.6.2 Product e operation catalog consigliati
Esempio di product:
{
"code": "RETAIL_EUR_ACCOUNT",
"name": "Retail EUR Account",
"currencyCode": "EUR",
"status": "ACTIVE"
}
Esempio di operation catalog neutrale:
| Operation code | Nome funzionale | Direction | Channel | Amount required | Perché serve |
|---|---|---|---|---|---|
ACCOUNT_OPENING |
Apertura conto | NEUTRAL |
ACCOUNT_SERVICE |
No | Serve se vuoi rendere esplicita una fee di apertura, anche quando è zero. |
MONTHLY_MAINTENANCE |
Canone mensile conto | DEBIT |
ACCOUNT_SERVICE |
No | Operazione schedulata dal sistema chiamante per calcolare eventuale canone. |
INCOMING_STANDARD_TRANSFER |
Bonifico entrante standard | CREDIT |
TRANSFER |
Yes | Può consumare capacità di funding o controllare il saldo massimo. |
INCOMING_INSTANT_TRANSFER |
Bonifico entrante istantaneo | CREDIT |
TRANSFER |
Yes | Stesso dominio del bonifico entrante, ma distinguibile per pricing o audit. |
OUTGOING_STANDARD_TRANSFER |
Bonifico uscente standard | DEBIT |
TRANSFER |
Yes | Può consumare limiti mensili e quota annuale inclusa. |
OUTGOING_INSTANT_TRANSFER |
Bonifico uscente istantaneo | DEBIT |
TRANSFER |
Yes | Può avere fee o quota diversa da quello standard. |
INTERNATIONAL_TRANSFER |
Trasferimento area estera | DEBIT |
TRANSFER |
Yes | Esempio classico di fee fissa o limite più restrittivo. |
DIRECT_DEBIT_COLLECTION |
Addebito diretto | DEBIT |
DIRECT_DEBIT |
Yes | Può essere gratuito ma comunque consumare limiti globali. |
DIRECT_DEBIT_REVOCATION |
Revoca addebito diretto | DEBIT |
DIRECT_DEBIT |
No | Può avere fee fissa. |
DIRECT_DEBIT_CHARGEBACK |
Contestazione addebito diretto | DEBIT |
DIRECT_DEBIT |
No | Può avere fee fissa superiore. |
P2P_PAYMENT |
Pagamento persona a persona | DEBIT |
DIGITAL_PAYMENT |
Yes | Può avere fee solo sopra una soglia importo. |
MERCHANT_PAYMENT |
Pagamento esercente | DEBIT |
DIGITAL_PAYMENT |
Yes | Tipicamente gratuito lato cliente. |
PUBLIC_SERVICE_PAYMENT |
Pagamento servizio pubblico | DEBIT |
DIGITAL_PAYMENT |
Yes | Può avere fee fissa. |
TRANSFER_REVERSAL |
Storno o rimborso trasferimento | DEBIT |
EXCEPTION |
No | Fee operativa per gestione eccezioni. |
2.6.3 Dimensioni da configurare e perché
Queste dimensioni coprono scenari reali di limiti e fee senza mettere logica nascosta nei sistemi integratori.
| Dimensione | Source | Tipo | Valori | Configurazione consigliata | Uso pratico |
|---|---|---|---|---|---|
transfer_speed |
REQUEST_METADATA |
ENUM |
STANDARD, INSTANT |
isRuleEnabled = true, canUseInCounterScopes = false |
Serve quando un unico codice operazione rappresenta più varianti e vuoi applicare fee diverse a standard e istantaneo. Non serve come counter scope se il limite è unico per tutti i trasferimenti. |
destination_area |
REQUEST_METADATA |
ENUM |
DOMESTIC, REGIONAL, INTERNATIONAL |
isRuleEnabled = true, canUseInCounterScopes = true solo se vuoi limiti separati per area |
Serve per applicare una fee diversa ai trasferimenti esteri o per separare i limiti per area destinazione. |
amount_band |
REQUEST_METADATA |
ENUM |
UP_TO_35, ABOVE_35 |
isRuleEnabled = true, canUseInCounterScopes = false |
Serve per regole tipo "gratis fino a 35 EUR, poi 0,30 EUR". Il chiamante calcola la fascia dall'importo e LimitRail la usa per scegliere la fee. |
projected_balance_after_operation |
REQUEST_METADATA |
DECIMAL |
Nessuna lista | isRuleEnabled = true, canUseInCounterScopes = false, isStoredInRuntimeLog = true se vuoi audit |
Serve per bloccare operazioni entranti che porterebbero il conto oltre il saldo massimo. Il valore deve arrivare dal sistema che possiede il saldo. |
average_monthly_balance |
REQUEST_METADATA o ACCOUNT_ATTRIBUTE |
DECIMAL |
Nessuna lista | isRuleEnabled = true, canUseInCounterScopes = false |
Serve per decidere se applicare il canone mensile. Se cambia ogni mese, invialo come metadata della chiamata MONTHLY_MAINTENANCE. |
customer_profile |
ACCOUNT_ATTRIBUTE |
ENUM |
STANDARD, PREMIUM, STAFF, RESTRICTED |
isRuleEnabled = true, canUseInCounterScopes = false |
Serve per condizioni commerciali o operative legate al profilo del conto. Esempio: staff senza canone, profilo restricted con limiti più bassi. |
limit_exception_granted |
REQUEST_METADATA |
BOOLEAN |
true/false | isRuleEnabled = true, canUseInCounterScopes = false, isSensitive = true se non vuoi mostrarla |
Serve quando un sistema operativo ha approvato una deroga su una singola operazione. LimitRail legge il flag e applica una regola alternativa. |
Nota importante: canUseInCounterScopes va acceso solo quando vuoi davvero separare i contatori. Per destination_area può avere senso: 1.000 EUR verso area domestica e 1.000 EUR verso area internazionale possono consumare contenitori diversi. Per amount_band no: separare i contatori per fascia importo renderebbe più difficile leggere il limite e raramente corrisponde al comportamento commerciale.
2.6.4 Esempio: volume transazioni 2.400 EUR al mese
Obiettivo: ogni account può movimentare al massimo 2.400 EUR al mese sulle operazioni monitorate.
Configurazione:
- crea una limit rule
LIM_MONTHLY_VOLUME_2400; MetricType = AMOUNT;PeriodType = MONTHLY;LimitAmount = 2400.00;IsBlocking = true;CounterScopeMode = ACCOUNT_GLOBALse il limite è unico per account;OperationScope = GLOBALse devono contribuire tutte le operazioni valutate dalla policy;WindowTimeZone = Europe/Romese il mese deve seguire il calendario italiano.
Effetto: se l'account ha già consumato 2.180 EUR nel mese e arriva un'operazione da 300 EUR, il motore calcola 2.480 EUR proiettati e restituisce DENIED_BY_POLICY con il codice regola LIM_MONTHLY_VOLUME_2400.
2.6.5 Esempio: 9 trasferimenti inclusi all'anno, poi 0,35 EUR
Obiettivo: i primi 9 trasferimenti annui sono inclusi; dal decimo in poi il cliente paga 0,35 EUR per operazione.
Configurazione nativa se la quota è per operation code:
- pricing rule
FEE_OUT_TRANSFER_YEARLY_TIER; CalculationMethod = TIERED;MetricType = COUNT;PeriodType = YEARLY;OperationScope = OPERATION_CODE;OperationCode = OUTGOING_STANDARD_TRANSFER;- tiers:
[
{ "upTo": 9, "amount": 0.00 },
{ "upTo": null, "amount": 0.35 }
]
Come leggerla: fino a quando il contatore annuo dell'account per OUTGOING_STANDARD_TRANSFER è sotto 9, la fee calcolata è zero. Dal trasferimento successivo, la fee diventa 0,35 EUR.
Attenzione: oggi il tiered pricing accumula su account + operation. Se vuoi una quota unica condivisa fra OUTGOING_STANDARD_TRANSFER e OUTGOING_INSTANT_TRANSFER, hai due strade:
- modellare un unico operation code
OUTGOING_TRANSFERe distinguere standard/istantaneo con la dimensionetransfer_speed; - oppure accettare due quote separate, una per operation code.
2.6.6 Esempio: pagamento persona a persona gratuito fino a 35 EUR
Obiettivo: il pagamento persona a persona è gratuito fino a 35 EUR; sopra 35 EUR costa 0,30 EUR.
Poiché oggi le condizioni leggono dimensioni governate, configura una dimensione:
{
"code": "amount_band",
"displayName": "Amount band",
"dataType": "ENUM",
"source": "REQUEST_METADATA",
"allowedValues": ["UP_TO_35", "ABOVE_35"],
"isRuleEnabled": true
}
Il sistema chiamante invia:
{
"externalAccountRef": "acc_000203",
"operationCode": "P2P_PAYMENT",
"amount": 48.00,
"currencyCode": "EUR",
"metadata": {
"amount_band": "ABOVE_35"
},
"mode": "PREVIEW"
}
Pricing:
- regola
WAIVERcon condizioneamount_band = UP_TO_35; - regola
FIXED 0.30 EURcon condizioneamount_band = ABOVE_35.
Questo è esplicito e auditabile: LimitRail non deve indovinare la fascia, ma può spiegare quale fascia ha ricevuto e quale fee ha applicato.
2.6.7 Esempio: canone mensile basato su saldo medio
Obiettivo: canone gratuito se il saldo medio mensile è almeno 220 EUR; altrimenti 0,70 EUR.
LimitRail non calcola il saldo medio. Il sistema che possiede i saldi deve calcolarlo e chiamare LimitRail con una operation schedulata:
{
"externalAccountRef": "acc_000203",
"operationCode": "MONTHLY_MAINTENANCE",
"amount": 0,
"currencyCode": "EUR",
"metadata": {
"average_monthly_balance": 186.40
},
"mode": "PREVIEW"
}
Configurazione:
- dimensione
average_monthly_balance, tipoDECIMAL, sourceREQUEST_METADATA; - pricing rule
FIXED 0.70 EUR; - condizione:
average_monthly_balance < 220.
Se il valore è 186,40, la fee si applica. Se il valore è 220 o superiore, la regola non scatta e non viene addebitato canone.
2.6.8 Esempio: saldo massimo conto
Obiettivo: impedire che un accredito porti il saldo del conto sopra 3.600 EUR.
LimitRail non ha il saldo contabile. Il chiamante deve inviare il saldo proiettato dopo l'operazione:
{
"externalAccountRef": "acc_000203",
"operationCode": "INCOMING_STANDARD_TRANSFER",
"amount": 280.00,
"currencyCode": "EUR",
"metadata": {
"projected_balance_after_operation": 3650.00
},
"mode": "PREVIEW"
}
Configurazione possibile:
- dimensione
projected_balance_after_operation, tipoDECIMAL, sourceREQUEST_METADATA; - limit rule
LIM_MAX_BALANCE_3600; MetricType = AMOUNT;PeriodType = SINGLE;LimitAmount = 0;IsBlocking = true;- condizione:
projected_balance_after_operation > 3600.
Come leggerla: la regola non sta usando i contatori storici; sta usando il valore calcolato dal sistema saldo. Quando il saldo proiettato supera 3.600 EUR, qualsiasi accredito positivo viene negato dalla policy. Se vuoi gestire tolleranze o deroghe, aggiungi la dimensione limit_exception_granted e una regola alternativa più permissiva.
2.6.9 Esempio: eccezione temporanea
Obiettivo: consentire una singola operazione anche se supera una policy standard, perché un operatore autorizzato ha concesso una deroga.
Configurazione:
- dimensione
limit_exception_granted, tipoBOOLEAN, sourceREQUEST_METADATA; isRuleEnabled = true;isSensitive = truese non vuoi esporre il valore nella risposta leggibile;- regola standard blocking senza deroga;
- regola alternativa o assenza di blocco quando
limit_exception_granted = true.
Runtime request payload:
{
"externalAccountRef": "acc_000203",
"operationCode": "INCOMING_STANDARD_TRANSFER",
"amount": 280.00,
"currencyCode": "EUR",
"metadata": {
"projected_balance_after_operation": 3650.00,
"limit_exception_granted": true
},
"mode": "RESERVE_CAPACITY",
"idempotencyKey": "reserve-acc_000203-20260613-001"
}
LimitRail può registrare che la decisione è stata valutata con una deroga, ma non sostituisce il workflow autorizzativo. Chi approva la deroga, con quali ruoli e per quanto tempo, resta responsabilità del sistema di gestione operativa a monte.
3. Condition plan e versioni
Il condition plan è il pacchetto di regole di pricing e limite. Una versione può essere:
DRAFT: modificabile;PUBLISHED: usata dal runtime e non modificabile;ARCHIVED: storica.
Le API runtime pubbliche non accettano override della versione. La chiamata runtime pubblica risolve sempre la versione pubblicata corretta per account, segmento o prodotto. Per confronti con una draft si usa la superficie admin di simulazione, non /v1/policy/evaluate.
3.1 Ordine di risoluzione policy
Quando arriva una richiesta runtime, LimitRail risolve la policy in questo ordine:
- override specifico account;
- policy specifica del segmento;
- policy di default del prodotto.
Questo significa:
- l'override account è un'eccezione per un singolo account, per esempio un limite negoziato o una condizione commerciale temporanea;
- la policy di segmento si usa solo quando un gruppo di account dello stesso prodotto deve seguire regole pubblicate diverse, per esempio studenti, premium, dipendenti, non residenti o account in migrazione;
- la policy di default del prodotto è la configurazione normale e viene usata quando non esistono override account o policy specifiche per il segmento.
Il segmento è opzionale. Non creare segmenti solo perché il campo esiste. Usalo solo quando il business sa spiegare perché quel gruppo deve avere fee, limiti o vincoli operativi diversi dal default del prodotto.
Se non trova una condition plan version pubblicata, la decisione non può applicare regole e il reason code indica assenza di policy.
4. Account onboarding
4.1 Account contract
Un account contract collega un account esterno a un prodotto LimitRail.
Payload consigliato:
{
"externalAccountRef": "000100000203",
"productId": "865e0567-7927-4680-a2f5-e4c71921b7bf",
"segmentCode": "PRIVATE",
"openedAtUtc": "2026-06-13T09:00:00Z",
"attributes": {
"customer_tier": "GOLD",
"residency": "IT"
}
}
Note:
externalAccountRefdeve essere opaco e stabile;- non usare IBAN, nome, email, codice fiscale o dati personali;
attributesviene validato contro le dimensions con sourceACCOUNT_ATTRIBUTE;- l'inserimento account e attributi deve essere atomico.
4.2 Segment
Il segmento è opzionale. È un gruppo business usato dalla risoluzione policy, non un campo obbligatorio di classificazione cliente.
Usalo quando lo stesso prodotto ha più di una policy pubblicata perché un gruppo di account richiede regole diverse. Esempi tipici:
PRIVATE;BUSINESS;VIP;NON_RESIDENT;EMPLOYEE.
Per esempio, se PAYMENT_ACCOUNT ha una policy standard e una policy
dipendenti, gli account con segmentCode = EMPLOYEE possono risolvere la
condition plan version dei dipendenti. Gli account senza segmento, o con un
segmento senza assegnazione, ricadono sul default del prodotto.
Se non esistono policy di segmento, lascia segmentCode vuoto. Non bisogna
inventare segmenti solo per riempire il campo.
4.3 Account override
Un override account assegna una policy pubblicata a un account specifico. È utile per:
- accordi corporate;
- condizioni negoziate;
- eccezioni commerciali temporanee;
- clienti con limiti speciali.
Se non esiste override, il runtime usa la policy specifica del segmento quando esiste; altrimenti usa la policy di default del prodotto.
5. OAuth client e scope
L'integrazione pubblica usa OAuth2/OIDC con client_credentials.
Token request:
POST /connect/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
client_id=lr_...
client_secret=...
scope=limitrail.catalog.read limitrail.accounts.read limitrail.accounts.write limitrail.evaluate limitrail.usage.write
Scope:
| Scope | Uso |
|---|---|
limitrail.catalog.read |
discovery di prodotti, operazioni e dimensions. |
limitrail.accounts.read |
lettura account, pricing risolto e contatori. |
limitrail.accounts.write |
registrazione account e attributi. |
limitrail.evaluate |
preview, reserve o commit diretto della policy runtime. |
limitrail.usage.write |
commit, cancel reservation, reverse usage. |
limitrail.audit.read |
lettura audit runtime quando logging è abilitato. |
Il token scade. Il client deve rinnovarlo prima della scadenza e non salvarlo come segreto permanente.
6. Flusso tecnico consigliato

Core->>API: GET /v1/products
Core->>API: GET /v1/operations
Core->>API: POST /v1/account-contracts
Core->>API: POST /v1/policy/evaluate
Core->>API: POST /v1/usage/commit
-->
### Step 1 - Catalog discovery
L'integratore legge il catalogo per verificare codici e dimensioni:
```http
GET /v1/products?take=25
GET /v1/operations?take=25
GET /v1/policy-dimensions
Uso pratico:
- verificare che
STD_ACCOUNTesista; - verificare che
A14sia attiva; - leggere quali metadata sono ammessi e da dove devono arrivare;
- costruire UI o validazioni lato integratore senza hardcodare tutto.
Step 2 - Account onboarding
Per ogni account esistente o nuovo:
POST /v1/account-contracts
Authorization: Bearer <token>
Content-Type: application/json
Se gli account sono milioni, il caricamento va fatto a batch. La UI deve cercare per prefisso e caricare a pagina/cursore, non contare tutto.
Step 3 - Runtime preview prima dell'esecuzione
Preview non scrive contatori e non crea reservation. Serve per mostrare fee, verificare policy o fare una pre-verifica.
POST /v1/policy/evaluate
Authorization: Bearer <token>
Content-Type: application/json
{
"externalAccountRef": "000100000203",
"operationCode": "A14",
"amount": 2500.00,
"currencyCode": "EUR",
"externalOperationRef": "wire-2026-000001",
"metadata": {
"wire_country_destination": "FRA"
},
"mode": "PREVIEW"
}
Risposta tipica:
{
"decision": "FEE_CALCULATED",
"reasonCode": "FEE_A14_1",
"originalAmount": 2500.00,
"totalFees": 0.40,
"currencyCode": "EUR",
"conditionPlanCode": "STD_ACCOUNT_PLAN",
"conditionPlanVersionNumber": 1,
"fees": [
{
"ruleCode": "FEE_A14_1",
"amount": 0.40,
"currencyCode": "EUR"
}
],
"usedDimensions": {
"operation": "A14",
"channel": "WIRE_TRANSFER",
"product": "STD_ACCOUNT",
"currency": "EUR",
"wire_country_destination": "FRA"
},
"missingDimensions": [],
"unusedDimensions": []
}
Step 4 - Reserve capacity
Reserve crea una prenotazione temporanea dei limiti. Serve quando l'operazione può fallire dopo la verifica.
{
"externalAccountRef": "000100000203",
"operationCode": "A14",
"amount": 2500.00,
"currencyCode": "EUR",
"externalOperationRef": "wire-2026-000001",
"metadata": {
"wire_country_destination": "FRA"
},
"mode": "RESERVE_CAPACITY",
"idempotencyKey": "reserve-wire-2026-000001"
}
Se la decisione è consentita, la risposta contiene:
capacityReservationId;capacityReservationExpiresAtUtc;- fee e limit impacts calcolati.
Step 5 - Commit usage
Commit conferma l'uso dei contatori. Può avvenire in due modi:
- commit di una reservation già creata;
- commit diretto tramite
POST /v1/policy/evaluateconmode = COMMIT_USAGE.
Commit di reservation:
{
"capacityReservationId": "2e337d1a-0b51-4fd5-a90a-4dcc7a47fd50",
"idempotencyKey": "commit-wire-2026-000001",
"externalAccountRef": "000100000203",
"operationCode": "A14",
"amount": 2500.00,
"currencyCode": "EUR",
"externalOperationRef": "wire-2026-000001",
"metadata": {
"wire_country_destination": "FRA"
}
}
La reservation deve combaciare con account, operation, amount, currency ed external operation reference. Se non combacia, il runtime rifiuta il commit.
Step 6 - Cancel reservation
Cancel si usa quando una reservation non deve diventare usage committed:
{
"capacityReservationId": "2e337d1a-0b51-4fd5-a90a-4dcc7a47fd50",
"reason": "Operation expired before execution"
}
Step 7 - Reverse usage
Reverse storna un usage già committed. Non è la stessa cosa di cancel:
- cancel = reservation non confermata;
- reverse = usage già applicato da compensare.
{
"reversalIdempotencyKey": "reverse-wire-2026-000001",
"reason": "Transfer cancelled after settlement rejection",
"reversedAtUtc": "2026-06-13T11:20:00Z"
}
7. Come leggere una decisione denied
Una decisione DENIED_BY_POLICY significa che LimitRail ha trovato una regola limite blocking che verrebbe superata. Il campo reasonCode contiene il codice della regola che ha bloccato.
Campi utili:
| Campo | Come leggerlo |
|---|---|
decision |
Esito di policy. Non è autorizzazione finanziaria finale. |
reasonCode |
ALLOWED, NO_CONDITION_PLAN oppure codice regola che ha prodotto l'esito. |
ruleResults |
Dettaglio delle regole valutate. |
limitImpacts |
Quali scope contatore sarebbero impattati. |
usedDimensions |
Dimensioni effettivamente entrate nel contesto e non sensibili. |
missingDimensions |
Dimensioni referenziate da regole o scope ma non presenti nel contesto. |
unusedDimensions |
Metadata inviati ma non referenziati da regole o scope. |
Esempio: se reasonCode = "LIM_A14_1" e ruleResults mostra projected amount oltre soglia, il racconto corretto è: "la policy ha negato perché il limite configurato dalla regola LIM_A14_1 sarebbe stato superato".
8. Counter scope: perché conta
Il counter scope è il perimetro del contatore: decide "dove finisce" il consumo di una operazione. È uno dei concetti più importanti del prodotto, perché lo stesso limite può essere interpretato in modi molto diversi.
Esempio semplice:
- un cliente fa tre bonifici
A14da 1.000 EUR; - LimitRail deve decidere se quei 3.000 EUR consumano un unico limite globale, un limite solo dei bonifici, un limite del canale wire transfer o un limite separato per paese destinazione.
Questa scelta non è tecnica: è business. Decide come il prodotto controlla il comportamento del cliente.
| Mode | Aggregazione |
|---|---|
ACCOUNT_OPERATION |
account + operation. Esempio: totale A14 giornaliero dell'account. |
ACCOUNT_CHANNEL |
account + channel. Esempio: totale canale WIRE_TRANSFER. |
ACCOUNT_GLOBAL |
solo account. Esempio: limite giornaliero globale. |
CUSTOM_DIMENSIONS |
account + dimensions configurate. Esempio: account + operation + paese destinazione. |
8.1 Esempi di business
Limite globale giornaliero account
Obiettivo: il cliente non può consumare più di 20.000 EUR al giorno su tutte le operazioni monitorate.
Configurazione:
- mode:
ACCOUNT_GLOBAL; - periodo:
DAILY; - metrica:
AMOUNT; - soglia: 20.000 EUR.
Risultato: bonifici, pagamenti e altre operazioni consumano lo stesso contenitore giornaliero dell'account.
Limite per tipo operazione
Obiettivo: il cliente può fare massimo 10.000 EUR al giorno di bonifici internazionali A14.
Configurazione:
- mode:
ACCOUNT_OPERATION; - operation:
A14; - periodo:
DAILY; - soglia: 10.000 EUR.
Risultato: solo le operazioni A14 consumano quel contatore. Altre operazioni hanno contatori separati.
Limite per canale
Obiettivo: limitare tutto il canale WIRE_TRANSFER, indipendentemente dal singolo codice operazione.
Configurazione:
- mode:
ACCOUNT_CHANNEL; - channel:
WIRE_TRANSFER; - periodo:
DAILY; - soglia: 15.000 EUR.
Risultato: più codici operazione dello stesso canale consumano lo stesso limite.
Limite per paese destinazione
Obiettivo: controllare separatamente i bonifici verso paesi diversi.
Configurazione:
- mode:
CUSTOM_DIMENSIONS; - dimensione:
wire_country_destination; - periodo:
DAILY; - soglia: 10.000 EUR per paese.
Risultato: il consumo verso FRA non si somma al consumo verso USA. Ogni paese ha il suo contatore per quell'account.
Se una dimensione è usata nel perimetro del contatore, deve essere presente nella richiesta o configurata con includeWhenMissing. Attenzione alle dimensioni ad alta cardinalità: usare un valore come transaction id, reference operazione o descrizione libera creerebbe troppi contatori e peggiorerebbe costi e performance.
9. Audit e runtime logging
Audit & Explain mostra solo valutazioni salvate. Se logging mode è NONE, la pagina resta vuota.
Logging mode:
NONE: nessuna evaluation loggata;DENIED_ONLY: logga solo denied;SAMPLED: logga un campione;FULL: logga tutto, utile per demo o diagnosi, costoso in produzione.
Le query audit richiedono sempre From e To. Questo evita scansioni su tabelle runtime grandi.
10. Regole pratiche per integratori
- Usare sempre enum uppercase:
ACTIVE,PREVIEW,RESERVE_CAPACITY,COMMIT_USAGE,DAILY,MONTHLY. - Non inviare dati personali in
externalAccountRef. - Inviare solo metadata registrati nel registry.
- Usare
idempotencyKeyper tutte le chiamate che scrivono stato. - Non riutilizzare la stessa idempotency key per payload diversi.
- Rinnovare il token prima della scadenza.
- Gestire
400,401,403,404,409,422come errori funzionali. - Usare search per prefisso e cursor/load-more sulle liste grandi.
Appendice A - Playbook operativo di configurazione e integrazione
Questo playbook è una checklist prescrittiva. Parte dai casi più semplici e arriva ai casi più articolati. Ogni scenario dice:
- dove configurare il caso nel backoffice;
- quale campo valorizzare;
- quale effetto produce nel motore;
- quale chiamata deve fare il sistema chiamante.
A.1 Setup minimo del prodotto
Obiettivo: avere un prodotto attivo con operazioni, policy pubblicata e credenziali OAuth.
| Step | Dove vai | Cosa imposti | Valore di esempio | Effetto |
|---|---|---|---|---|
| 1 | Product Workspace | Product code |
RETAIL_EUR_ACCOUNT |
Codice stabile che l'integratore leggerà da /v1/products. |
| 2 | Product Workspace | currencyCode |
EUR |
Valuta base del prodotto. |
| 3 | Operation Catalog | Operation code | OUTGOING_TRANSFER |
Codice che il chiamante userà in operationCode. |
| 4 | Operation Catalog | direction |
DEBIT |
Dice al runtime che l'operazione consuma capacità. |
| 5 | Operation Catalog | channelCode |
TRANSFER |
Permette limiti e fee per intero canale. |
| 6 | Operation Catalog | requiresAmount |
true |
La chiamata runtime viene rifiutata se manca amount. |
| 7 | Condition plans | Crea condition plan | RETAIL_EUR_PLAN |
Contenitore delle regole di fee e limiti. |
| 8 | Policy Studio | Pubblica versione | PUBLISHED |
Solo una versione pubblicata è usata dalle API runtime. |
| 9 | Product Workspace | Collega plan al product | defaultConditionPlanId |
Il runtime risolve la policy dal prodotto se non esistono override. |
| 10 | Developer access | Crea OAuth client | scope necessari | Il chiamante può ottenere token e chiamare le API pubbliche. |
Chiamate minime del sistema chiamante:
POST /connect/token
GET /v1/products?take=25
GET /v1/operations?take=25
GET /v1/policy-dimensions
POST /v1/account-contracts
POST /v1/policy/evaluate
Token request:
POST /connect/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
client_id=lr_...
client_secret=...
scope=limitrail.catalog.read limitrail.accounts.read limitrail.accounts.write limitrail.evaluate limitrail.usage.write
Token response:
{
"access_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "limitrail.catalog.read limitrail.accounts.read limitrail.accounts.write limitrail.evaluate limitrail.usage.write"
}
Discovery response essenziale:
[
{
"id": "865e0567-7927-4680-a2f5-e4c71921b7bf",
"externalCoreProductRef": null,
"code": "RETAIL_EUR_ACCOUNT",
"name": "Retail EUR Account",
"status": "ACTIVE",
"currencyCode": "EUR"
}
]
A.2 Operazione gratuita esplicita
Usala quando vuoi dimostrare che un'operazione è inclusa nel prodotto, non semplicemente "senza regola".
| Dove vai | Campo | Valore |
|---|---|---|
| Operation Catalog | code |
MERCHANT_PAYMENT |
| Operation Catalog | direction |
DEBIT |
| Operation Catalog | requiresAmount |
true |
| Policy Studio > Pricing | CalculationMethod |
WAIVER |
| Policy Studio > Pricing | OperationScope |
OPERATION_CODE |
| Policy Studio > Pricing | OperationCode |
MERCHANT_PAYMENT |
Effetto: la risposta può mostrare fee a zero e rendere chiaro che la gratuità è una scelta di prodotto.
API request - preview fee:
POST /v1/policy/evaluate
Authorization: Bearer <token>
Content-Type: application/json
{
"externalAccountRef": "acc_000203",
"operationCode": "MERCHANT_PAYMENT",
"amount": 42.00,
"currencyCode": "EUR",
"mode": "PREVIEW"
}
API response:
{
"decision": "FEE_CALCULATED",
"reasonCode": "FEE_MERCHANT_PAYMENT_INCLUDED",
"originalAmount": 42.00,
"totalFees": 0.00,
"currencyCode": "EUR",
"fees": [
{
"code": "FEE_MERCHANT_PAYMENT_INCLUDED",
"amount": 0.00,
"currencyCode": "EUR",
"description": "Merchant payment included"
}
],
"usedDimensions": {
"operation": "MERCHANT_PAYMENT",
"channel": "DIGITAL_PAYMENT",
"product": "RETAIL_EUR_ACCOUNT",
"currency": "EUR"
}
}
A.3 Fee fissa per singola operazione
Usala quando ogni esecuzione dell'operazione costa sempre lo stesso importo.
| Dove vai | Campo | Valore |
|---|---|---|
| Operation Catalog | code |
PUBLIC_SERVICE_PAYMENT |
| Policy Studio > Pricing | CalculationMethod |
FIXED |
| Policy Studio > Pricing | FixedAmount |
0.35 |
| Policy Studio > Pricing | CurrencyCode |
EUR |
| Policy Studio > Pricing | AppliesWhen |
ON_EVALUATE |
Effetto: ogni richiesta runtime per PUBLIC_SERVICE_PAYMENT restituisce una fee di 0,35 EUR se la policy è risolta e la regola non ha condizioni che la escludono.
API request - preview fee:
POST /v1/policy/evaluate
Authorization: Bearer <token>
Content-Type: application/json
{
"externalAccountRef": "acc_000203",
"operationCode": "PUBLIC_SERVICE_PAYMENT",
"amount": 88.00,
"currencyCode": "EUR",
"mode": "PREVIEW"
}
API response:
{
"decision": "FEE_CALCULATED",
"reasonCode": "FEE_PUBLIC_SERVICE_PAYMENT",
"originalAmount": 88.00,
"totalFees": 0.35,
"currencyCode": "EUR",
"fees": [
{
"code": "FEE_PUBLIC_SERVICE_PAYMENT",
"amount": 0.35,
"currencyCode": "EUR",
"description": "Public service payment fee"
}
]
}
A.4 Fee percentuale con minimo e massimo
Usala per commissioni proporzionali all'importo, ma con guardrail commerciale.
| Dove vai | Campo | Valore |
|---|---|---|
| Policy Studio > Pricing | CalculationMethod |
PERCENTAGE |
| Policy Studio > Pricing | PercentageRate |
0.0025 |
| Policy Studio > Pricing | MinAmount |
0.20 |
| Policy Studio > Pricing | MaxAmount |
4.50 |
| Policy Studio > Pricing | FeeBase |
OPERATION_AMOUNT |
Effetto: su 800 EUR la fee teorica è 2,00 EUR. Su importi piccoli il minimo evita fee troppo basse; su importi alti il massimo evita fee troppo alte.
A.5 Volume mensile massimo per account
Usalo quando il prodotto ha un massimale mensile di movimentazione.
| Dove vai | Campo | Valore |
|---|---|---|
| Policy Studio > Limits | Code |
LIM_MONTHLY_VOLUME_2400 |
| Policy Studio > Limits | MetricType |
AMOUNT |
| Policy Studio > Limits | PeriodType |
MONTHLY |
| Policy Studio > Limits | LimitAmount |
2400.00 |
| Policy Studio > Limits | CounterScopeMode |
ACCOUNT_GLOBAL |
| Policy Studio > Limits | OperationScope |
GLOBAL |
| Policy Studio > Limits | IsBlocking |
true |
Effetto: tutte le operazioni valutate dalla policy consumano lo stesso contenitore mensile dell'account. Se il nuovo importo porta il totale sopra 2.400 EUR, la decisione diventa DENIED_BY_POLICY.
API request - reserve capacity:
POST /v1/policy/evaluate
Authorization: Bearer <token>
Content-Type: application/json
{
"externalAccountRef": "acc_000203",
"operationCode": "OUTGOING_TRANSFER",
"amount": 300.00,
"currencyCode": "EUR",
"externalOperationRef": "op-20260613-0001",
"mode": "RESERVE_CAPACITY",
"idempotencyKey": "reserve-op-20260613-0001"
}
API response quando la capacità viene riservata:
{
"decision": "ALLOWED",
"reasonCode": "ALLOWED",
"capacityReservationId": "2e337d1a-0b51-4fd5-a90a-4dcc7a47fd50",
"capacityReservationExpiresAtUtc": "2026-06-13T10:20:00Z",
"limitImpacts": [
{
"metricType": "AMOUNT",
"periodType": "MONTHLY",
"projectedAmount": 300.00
}
]
}
API request - commit dopo esecuzione dell'operazione:
POST /v1/usage/commit
Authorization: Bearer <token>
Content-Type: application/json
{
"capacityReservationId": "2e337d1a-0b51-4fd5-a90a-4dcc7a47fd50",
"externalAccountRef": "acc_000203",
"operationCode": "OUTGOING_TRANSFER",
"amount": 300.00,
"currencyCode": "EUR",
"externalOperationRef": "op-20260613-0001",
"idempotencyKey": "commit-op-20260613-0001"
}
API response:
{
"usageEventId": "7c62f3dd-4ef0-48d0-a95c-9b7f8c0f2a10",
"status": "APPLIED"
}
A.6 Limite per operation code
Usalo quando vuoi limitare solo una famiglia specifica di operazioni, senza impattare le altre.
| Dove vai | Campo | Valore |
|---|---|---|
| Policy Studio > Limits | OperationScope |
OPERATION_CODE |
| Policy Studio > Limits | OperationCode |
OUTGOING_TRANSFER |
| Policy Studio > Limits | MetricType |
AMOUNT |
| Policy Studio > Limits | PeriodType |
DAILY |
| Policy Studio > Limits | LimitAmount |
900.00 |
| Policy Studio > Limits | CounterScopeMode |
ACCOUNT_OPERATION |
Effetto: solo OUTGOING_TRANSFER consuma questo limite giornaliero. Un pagamento esercente può avere un limite diverso o nessun limite specifico.
A.7 Limite per canale
Usalo quando più operation code devono consumare lo stesso limite, per esempio tutte le operazioni del canale trasferimenti.
| Dove vai | Campo | Valore |
|---|---|---|
| Operation Catalog | channelCode |
TRANSFER su tutte le operation correlate |
| Policy Studio > Limits | OperationScope |
OPERATION_CHANNEL |
| Policy Studio > Limits | ChannelCode |
TRANSFER |
| Policy Studio > Limits | MetricType |
AMOUNT |
| Policy Studio > Limits | PeriodType |
DAILY |
| Policy Studio > Limits | LimitAmount |
1200.00 |
| Policy Studio > Limits | CounterScopeMode |
ACCOUNT_CHANNEL |
Effetto: OUTGOING_TRANSFER e OUTGOING_INSTANT_TRANSFER, se hanno channelCode = TRANSFER, consumano lo stesso contenitore giornaliero.
A.8 Operazioni incluse, poi fee
Usalo per una quota inclusa: prime N operazioni gratuite, poi fee fissa.
| Dove vai | Campo | Valore |
|---|---|---|
| Policy Studio > Pricing | CalculationMethod |
TIERED |
| Policy Studio > Pricing | MetricType |
COUNT |
| Policy Studio > Pricing | PeriodType |
YEARLY |
| Policy Studio > Pricing | OperationCode |
OUTGOING_TRANSFER |
| Policy Studio > Pricing | Tiers[0].UpTo |
9 |
| Policy Studio > Pricing | Tiers[0].Amount |
0.00 |
| Policy Studio > Pricing | Tiers[1].UpTo |
vuoto |
| Policy Studio > Pricing | Tiers[1].Amount |
0.35 |
Effetto: finché il contatore annuo dell'account per OUTGOING_TRANSFER è sotto 9, la fee è zero. Dal trasferimento successivo, la fee è 0,35 EUR.
Nota di modellazione: il tiered pricing oggi conta per account + operation. Se vuoi una quota unica per standard e istantaneo, configura un unico operation code OUTGOING_TRANSFER e usa transfer_speed come dimensione.
A.9 Variante standard / istantanea sullo stesso operation code
Usala quando vuoi evitare quote separate ma vuoi comunque distinguere il caso standard dal caso istantaneo.
| Dove vai | Campo | Valore |
|---|---|---|
| Dimension Registry | code |
transfer_speed |
| Dimension Registry | dataType |
ENUM |
| Dimension Registry | source |
REQUEST_METADATA |
| Dimension Registry | allowedValues |
STANDARD, INSTANT |
| Dimension Registry | isRuleEnabled |
true |
| Dimension Registry | canUseInCounterScopes |
false |
| Policy Studio > Pricing | Condizione regola standard | transfer_speed = STANDARD |
| Policy Studio > Pricing | Condizione regola istantanea | transfer_speed = INSTANT |
Effetto: il contatore tiered resta su OUTGOING_TRANSFER, quindi la quota è condivisa. La fee può cambiare in base a transfer_speed.
API request - preview con variante:
POST /v1/policy/evaluate
Authorization: Bearer <token>
Content-Type: application/json
{
"externalAccountRef": "acc_000203",
"operationCode": "OUTGOING_TRANSFER",
"amount": 120.00,
"currencyCode": "EUR",
"metadata": {
"transfer_speed": "INSTANT"
},
"mode": "PREVIEW"
}
API response:
{
"decision": "FEE_CALCULATED",
"reasonCode": "FEE_OUTGOING_TRANSFER_INSTANT",
"totalFees": 0.35,
"currencyCode": "EUR",
"usedDimensions": {
"operation": "OUTGOING_TRANSFER",
"channel": "TRANSFER",
"transfer_speed": "INSTANT",
"product": "RETAIL_EUR_ACCOUNT",
"currency": "EUR"
}
}
A.10 Fee diversa per area destinazione
Usala quando una fee dipende da dove va il trasferimento.
| Dove vai | Campo | Valore |
|---|---|---|
| Dimension Registry | code |
destination_area |
| Dimension Registry | dataType |
ENUM |
| Dimension Registry | source |
REQUEST_METADATA |
| Dimension Registry | allowedValues |
DOMESTIC, REGIONAL, INTERNATIONAL |
| Dimension Registry | isRuleEnabled |
true |
| Dimension Registry | canUseInCounterScopes |
false per sola fee |
| Policy Studio > Pricing | Regola 1 | WAIVER se destination_area = DOMESTIC |
| Policy Studio > Pricing | Regola 2 | FIXED 0.65 EUR se destination_area = INTERNATIONAL |
Effetto: il sistema chiamante dichiara l'area destinazione, LimitRail valida il valore e applica la fee corretta.
A.11 Limite separato per area destinazione
Usalo quando il consumo verso aree diverse non deve finire nello stesso contatore.
| Dove vai | Campo | Valore |
|---|---|---|
| Dimension Registry | destination_area.canUseInCounterScopes |
true |
| Policy Studio > Limits | CounterScopeMode |
CUSTOM_DIMENSIONS |
| Policy Studio > Limits | Scope dimension | destination_area |
| Policy Studio > Limits | MetricType |
AMOUNT |
| Policy Studio > Limits | PeriodType |
MONTHLY |
| Policy Studio > Limits | LimitAmount |
1800.00 |
Effetto: 800 EUR verso DOMESTIC e 800 EUR verso INTERNATIONAL consumano due contatori diversi. Usa questa opzione solo se il prodotto vuole davvero separare i limiti per area.
A.12 Fee sopra soglia importo
Usala quando l'importo della singola operazione decide quale fee applicare.
| Dove vai | Campo | Valore |
|---|---|---|
| Dimension Registry | code |
amount_band |
| Dimension Registry | dataType |
ENUM |
| Dimension Registry | source |
REQUEST_METADATA |
| Dimension Registry | allowedValues |
UP_TO_35, ABOVE_35 |
| Dimension Registry | isRuleEnabled |
true |
| Policy Studio > Pricing | Regola gratuita | WAIVER se amount_band = UP_TO_35 |
| Policy Studio > Pricing | Regola a pagamento | FIXED 0.30 EUR se amount_band = ABOVE_35 |
Responsabilità del chiamante: calcolare la fascia dall'importo e inviarla nei metadata.
API request - preview sopra soglia:
POST /v1/policy/evaluate
Authorization: Bearer <token>
Content-Type: application/json
{
"externalAccountRef": "acc_000203",
"operationCode": "P2P_PAYMENT",
"amount": 48.00,
"currencyCode": "EUR",
"metadata": {
"amount_band": "ABOVE_35"
},
"mode": "PREVIEW"
}
API response:
{
"decision": "FEE_CALCULATED",
"reasonCode": "FEE_P2P_ABOVE_35",
"originalAmount": 48.00,
"totalFees": 0.30,
"currencyCode": "EUR",
"usedDimensions": {
"amount_band": "ABOVE_35",
"operation": "P2P_PAYMENT"
}
}
A.13 Canone mensile basato su saldo medio
Usalo quando una fee ricorrente dipende da un valore calcolato dal sistema contabile.
| Dove vai | Campo | Valore |
|---|---|---|
| Operation Catalog | code |
MONTHLY_MAINTENANCE |
| Dimension Registry | code |
average_monthly_balance |
| Dimension Registry | dataType |
DECIMAL |
| Dimension Registry | source |
REQUEST_METADATA |
| Dimension Registry | isRuleEnabled |
true |
| Policy Studio > Pricing | CalculationMethod |
FIXED |
| Policy Studio > Pricing | FixedAmount |
0.70 |
| Policy Studio > Pricing | Condizione | average_monthly_balance < 220 |
Responsabilità del chiamante: calcolare il saldo medio e chiamare LimitRail a fine periodo o nella schedulazione di billing.
API request - canone periodico:
POST /v1/policy/evaluate
Authorization: Bearer <token>
Content-Type: application/json
{
"externalAccountRef": "acc_000203",
"operationCode": "MONTHLY_MAINTENANCE",
"amount": 0,
"currencyCode": "EUR",
"metadata": {
"average_monthly_balance": 186.40
},
"mode": "PREVIEW"
}
API response:
{
"decision": "FEE_CALCULATED",
"reasonCode": "FEE_MONTHLY_MAINTENANCE_LOW_BALANCE",
"totalFees": 0.70,
"currencyCode": "EUR",
"usedDimensions": {
"average_monthly_balance": 186.40,
"operation": "MONTHLY_MAINTENANCE"
}
}
A.14 Saldo massimo conto
Usalo quando vuoi bloccare accrediti che porterebbero il conto oltre una soglia. LimitRail non calcola il saldo: legge il saldo proiettato fornito dal sistema chiamante.
| Dove vai | Campo | Valore |
|---|---|---|
| Dimension Registry | code |
projected_balance_after_operation |
| Dimension Registry | dataType |
DECIMAL |
| Dimension Registry | source |
REQUEST_METADATA |
| Dimension Registry | isRuleEnabled |
true |
| Policy Studio > Limits | Code |
LIM_MAX_BALANCE_3600 |
| Policy Studio > Limits | PeriodType |
SINGLE |
| Policy Studio > Limits | IsBlocking |
true |
| Policy Studio > Limits | Condizione | projected_balance_after_operation > 3600 |
API request - controllo saldo proiettato:
POST /v1/policy/evaluate
Authorization: Bearer <token>
Content-Type: application/json
{
"externalAccountRef": "acc_000203",
"operationCode": "INCOMING_STANDARD_TRANSFER",
"amount": 280.00,
"currencyCode": "EUR",
"metadata": {
"projected_balance_after_operation": 3650.00
},
"mode": "PREVIEW"
}
API response:
{
"decision": "DENIED_BY_POLICY",
"reasonCode": "LIM_MAX_BALANCE_3600",
"originalAmount": 280.00,
"totalFees": 0.00,
"currencyCode": "EUR",
"ruleResults": [
{
"ruleCode": "LIM_MAX_BALANCE_3600",
"decision": "DENIED_BY_POLICY",
"metricType": "AMOUNT",
"periodType": "SINGLE"
}
],
"usedDimensions": {
"projected_balance_after_operation": 3650.00,
"operation": "INCOMING_STANDARD_TRANSFER"
}
}
Effetto: la policy nega perché il saldo proiettato supera la soglia. L'esecuzione finanziaria resta responsabilità del chiamante.
A.15 Profilo account o segmento cliente
Usalo quando le condizioni dipendono da una caratteristica stabile del conto.
| Dove vai | Campo | Valore |
|---|---|---|
| Dimension Registry | code |
customer_profile |
| Dimension Registry | source |
ACCOUNT_ATTRIBUTE |
| Dimension Registry | dataType |
ENUM |
| Dimension Registry | allowedValues |
STANDARD, PREMIUM, STAFF, RESTRICTED |
| Dimension Registry | isRuleEnabled |
true |
| Account contracts | attributes.customer_profile |
PREMIUM |
| Policy Studio | Condizione | customer_profile = PREMIUM |
Effetto: il chiamante non deve rimandare questo valore a ogni richiesta runtime. LimitRail lo legge dagli attributi dell'account.
API request - creazione account contract:
POST /v1/account-contracts
Authorization: Bearer <token>
Content-Type: application/json
{
"externalAccountRef": "acc_000203",
"productId": "865e0567-7927-4680-a2f5-e4c71921b7bf",
"attributes": {
"customer_profile": "PREMIUM"
}
}
API response:
{
"id": "146dbd98-242f-4f5d-9fc0-b5dbb497cbb5",
"externalAccountRef": "acc_000203",
"productId": "865e0567-7927-4680-a2f5-e4c71921b7bf",
"productCode": "RETAIL_EUR_ACCOUNT",
"status": "ACTIVE"
}
A.16 Deroga operativa su singola operazione
Usala quando un sistema operativo approva una deroga e LimitRail deve tenerne conto nella valutazione.
| Dove vai | Campo | Valore |
|---|---|---|
| Dimension Registry | code |
limit_exception_granted |
| Dimension Registry | dataType |
BOOLEAN |
| Dimension Registry | source |
REQUEST_METADATA |
| Dimension Registry | isRuleEnabled |
true |
| Dimension Registry | isSensitive |
true se non deve apparire in risposta |
| Policy Studio | Regola restrittiva | applica quando limit_exception_granted non esiste o è false |
| Policy Studio | Regola alternativa | applica quando limit_exception_granted = true |
API request - deroga con riserva:
POST /v1/policy/evaluate
Authorization: Bearer <token>
Content-Type: application/json
{
"externalAccountRef": "acc_000203",
"operationCode": "INCOMING_STANDARD_TRANSFER",
"amount": 280.00,
"currencyCode": "EUR",
"metadata": {
"projected_balance_after_operation": 3650.00,
"limit_exception_granted": true
},
"mode": "RESERVE_CAPACITY",
"idempotencyKey": "reserve-exception-000203-001"
}
API response:
{
"decision": "ALLOWED",
"reasonCode": "ALLOWED",
"capacityReservationId": "4dfef774-f177-4642-8fb4-7c3dfaf09ea0",
"usedDimensions": {
"projected_balance_after_operation": 3650.00,
"operation": "INCOMING_STANDARD_TRANSFER"
}
}
Effetto: LimitRail valuta con la deroga. Non decide chi può approvarla: quello resta nel sistema operativo a monte.
A.17 Flusso runtime corretto: preview, reserve, commit
Usalo quando l'operazione può essere verificata, poi eseguita dopo una fase esterna.
| Step | API | Quando usarla | Cosa scrive |
|---|---|---|---|
| 1 | POST /v1/policy/evaluate con mode = PREVIEW |
Mostrare fee o controllare policy senza impegnare capacità | Nulla |
| 2 | POST /v1/policy/evaluate con mode = RESERVE_CAPACITY |
Bloccare temporaneamente capacità mentre il chiamante esegue l'operazione | Reservation temporanea |
| 3 | POST /v1/usage/commit |
Confermare che l'operazione è stata eseguita | Usage committed e contatori |
| 4 | POST /v1/capacity-reservations/{id}/cancel |
Annullare una reservation non eseguita | Cancella reservation |
| 5 | POST /v1/usage/{id}/reverse |
Compensare un usage già committed | Usage reversal |
Regola pratica: usa sempre idempotencyKey per reserve, commit e reverse. Non riutilizzare la stessa chiave per payload diversi.
A.18 Cosa deve leggere il chiamante per mostrare limiti e fee all'utente finale
| Bisogno del canale | API | Uso |
|---|---|---|
| Mostrare il pricing risolto del conto | GET /v1/accounts/{externalAccountRef}/pricing |
Elenco fee applicabili al prodotto/account. |
| Mostrare i contatori committed del conto | GET /v1/accounts/{externalAccountRef}/usage-counters |
Stato dei limiti consumati, senza dati operativi grezzi. |
| Simulare una operazione prima dell'esecuzione | POST /v1/policy/evaluate con PREVIEW |
Mostra fee e potenziale denied prima che l'utente confermi. |
| Impegnare capacità durante l'esecuzione | POST /v1/policy/evaluate con RESERVE_CAPACITY |
Evita race condition tra verifica ed esecuzione. |
API request - pricing risolto:
GET /v1/accounts/acc_000203/pricing
Authorization: Bearer <token>
API response:
{
"externalAccountRef": "acc_000203",
"productCode": "RETAIL_EUR_ACCOUNT",
"conditionPlanCode": "RETAIL_EUR_PLAN",
"versionNumber": 1,
"currencyCode": "EUR",
"pricing": [
{
"operationCode": "MERCHANT_PAYMENT",
"method": "WAIVER",
"summary": "Included in the account package"
},
{
"operationCode": "PUBLIC_SERVICE_PAYMENT",
"method": "FIXED",
"amount": 0.35,
"currencyCode": "EUR"
}
]
}
Uso reale: questa è la chiamata che un canale utente può usare per mostrare "quanto costa" una certa operazione prima di far partire un pagamento. Non consuma contatori.
API request - contatori committed:
GET /v1/accounts/acc_000203/usage-counters
Authorization: Bearer <token>
API response:
{
"externalAccountRef": "acc_000203",
"counters": [
{
"operationCode": "OUTGOING_TRANSFER",
"metricType": "AMOUNT",
"periodType": "MONTHLY",
"committedAmount": 620.00,
"limitAmount": 2400.00,
"remainingAmount": 1780.00,
"currencyCode": "EUR"
},
{
"operationCode": "OUTGOING_TRANSFER",
"metricType": "COUNT",
"periodType": "YEARLY",
"committedCount": 4,
"includedCount": 9,
"remainingIncludedCount": 5
}
]
}
Uso reale: questa è la chiamata che un'app o un portale può usare per mostrare "hai ancora 1.780 EUR disponibili questo mese" oppure "hai ancora 5 operazioni incluse". Non deve esporre eventi grezzi o movimenti contabili.
A.19 Matrice rapida dei casi coperti
| Caso d'uso | Configurazione principale | Input richiesto al chiamante |
|---|---|---|
| Operazione gratuita | Pricing WAIVER |
account, operation, amount se richiesto |
| Fee fissa | Pricing FIXED |
account, operation, amount se richiesto |
| Fee percentuale | Pricing PERCENTAGE |
account, operation, amount |
| N operazioni incluse poi fee | Pricing TIERED, COUNT, periodo |
account, operation, idempotency su write |
| Volume mensile massimo | Limit AMOUNT, MONTHLY |
account, operation, amount |
| Numero massimo operazioni | Limit COUNT, periodo |
account, operation |
| Limite per canale | ACCOUNT_CHANNEL |
operation con channelCode coerente |
| Limite per area | dimensione in CUSTOM_DIMENSIONS |
metadata destination_area |
| Fee per area | dimensione con isRuleEnabled |
metadata destination_area |
| Fee sopra soglia importo | dimensione amount_band |
metadata amount_band calcolato dal chiamante |
| Canone da saldo medio | dimensione average_monthly_balance |
metadata calcolato dal sistema saldo |
| Saldo massimo | dimensione projected_balance_after_operation |
saldo proiettato calcolato dal sistema saldo |
| Profilo cliente | account attribute | attributo su account contract |
| Deroga singola | dimensione limit_exception_granted |
metadata booleano autorizzato a monte |