payment_method on one account, which connections to use — payment providers, fraud screening, 3DS and authentication steps, or a smart routing step that picks the provider per payment — and lets you branch by buyer attributes (country, currency, amount, card brand, custom metadata, schedules, volume limits, …), react to each outcome (approval, decline, decline group, Merchant Advice Code, pending, error) and end the route with an action (cancel, capture, hold for review, revert).
Resource shape
route object
route.steps[]
Each step is a provider step (provider_id + connection_id: a payment, fraud, 3DS or authentication provider, see Provider step kinds), a smart routing step (provider_id: "SMART_ROUTING" + smart_routing, see Smart routing steps) or an action step (action). index values are contiguous starting at 1, counting every kind.
output[] entries
status enum
Provider step kinds
The kind of a provider step is derived from itsprovider_id and returned as provider_type. It decides which outcomes the step can have and what may follow it, the same way the dashboard does.
PENDING on a PAYMENT or smart routing step is rejected with 400 INVALID_ROUTE_CONFIGURATION (output PENDING is only supported on fraud, 3DS and authentication provider steps), and so is a PENDING that continues to another step on a fraud step that runs after the payment.
Fraud configuration. A FRAUD step carries the same configuration the dashboard edits, in the fraud object:
fraud on every FRAUD step (fields without a value are omitted, report_only always). On Update a Routing a fraud step sent without fraud keeps its stored configuration; a step sent with it replaces all six fields. fraud on a step that is not a fraud provider is rejected.
Evaluation rules
- The route enters at
index: 1, unlessstart_splitis set — then Yuno draws one entry step per payment according to the percentages. If the entry step is aCANCELstep, the payment is rejected and the route ends. - The provider call runs.
- Yuno walks
output[]top-to-bottom; the first entry whosestatus(plus the group predicate onDECLINE_GROUP,MAC_CODE_GROUPandSUCCEEDED_GROUP) matches the outcome wins. An entry withretry: trueruns the same provider once more first; the outcome of that second attempt decides. - If the matched entry has
next, jump to that step. If it hasnext_split, Yuno draws one of its steps per payment according to the percentages and jumps there. If neither is set or no entry matches, the route terminates with the actual provider outcome. - A jump to an action step performs the action (
CANCEL,CAPTURE,HOLD_FOR_REVIEW) and ends the route.
Outcome groups
A group is a named set of outcomes you keep on the account, so several routes can react to the same list without repeating it. The dashboard shows them under the routing settings; the API reads them with List Decline Groups and List Succeeded Groups and references them bygroup_id.
group_idmust be a group of the routing’s account and of the kind thestatusexpects. An unknown id, an id of another account, or a Merchant Advice Code group sent asDECLINE_GROUPis rejected with400 INVALID_ROUTE_CONFIGURATION;messagesnames thegroup_idand the kind it actually is.DECLINE_GROUPwithdecline_types[]and nogroup_idkeeps working as before: Yuno creates a decline group namedauto_…with those sub-statuses on every save. Prefergroup_idwhen the group already exists, so the account does not accumulate automatic groups.DECLINE_GROUPwith bothgroup_idanddecline_types[]is accepted only when the list equals the group’s members as a set (order does not matter). This is what lets you send a retrieved routing back unchanged, since responses return both. A different list is rejected: edit the group in the dashboard instead.MAC_CODE_GROUPandSUCCEEDED_GROUPrequiregroup_id;SUCCEEDED_GROUPdoes not acceptdecline_types[]. Create those groups in the dashboard first.- The same
group_idcannot appear twice in theoutput[]of one step. - Responses return
group_idandgroup_nameon every group entry, anddecline_types[]onDECLINE_GROUPandMAC_CODE_GROUPentries, in the same sub-status vocabulary the listing endpoints use.
Retry
retry: true on a DECLINED, INTERNAL_ERROR or DECLINE_GROUP entry tells Yuno to attempt the same provider once more when that outcome happens, before following the entry’s next / next_split. The second attempt uses the step’s other outputs as usual: if it is approved, the APPROVED path applies; if it fails again, the original destination of the entry applies. There is at most one retry per entry per payment.
retry: trueonAPPROVED,MAC_CODE_GROUPorSUCCEEDED_GROUPis rejected with400 INVALID_ROUTE_CONFIGURATION;retry: falseis accepted anywhere, which is what lets you send a retrieved routing back unchanged.- Responses always return
retryon every entry (falsewhen not set), so you can see which branches retry. - On Update a Routing, an entry sent without
retrykeeps the value already stored for that position; sendretry: falseexplicitly to turn a retry off.
Action steps
An action step ends the route with an action instead of calling a provider. It hasindex and action, no provider_id, connection_id or output, and it counts in the contiguous index sequence.
action_delay rules:
- Only with
action = CAPTURE; on any other step it is rejected. - ISO-8601 duration (
PT5M,PT3H,P2D,P1W), at least 1 minute (PT1M) and at most 7 days (P7D). - Omit it to capture as soon as the approval is processed (about one minute).
400 INVALID_ROUTE_CONFIGURATION; messages names the step and the rule (step index=N with action=CAPTURE must be reached only from an APPROVED or SUCCEEDED_GROUP output of a payment step, ... action=REVERT must be reached only from an output of a fraud step that runs after the payment, ... action=CANCEL must not be reached from an APPROVED or SUCCEEDED_GROUP output of a payment step). A CAPTURE, HOLD_FOR_REVIEW or REVERT step placed as the route entry or inside a start_split is rejected too.
On Update a Routing, a stored CAPTURE or HOLD_FOR_REVIEW step is kept when the request leaves it out and the output it hung from is sent without next, and a CAPTURE step sent without action_delay keeps the stored delay, the same “stored wins” rule as retry. To change the capture, send the step with its new action_delay; to remove it, point that output at another step. Leaving the step out of the request does not remove it.
Smart routing steps
A smart routing step lets Yuno pick the provider per payment among a set of connections, by cost or by latency, instead of fixing one. It is the API form of the dashboard’s Smart Routing box. UnlikeCAPTURE and HOLD_FOR_REVIEW, the step belongs to the request: an update that does not carry it removes it, so retrieve the routing first and send the step back when you change something else. See Update a Routing.
- Only on routings with
payment_method = "CARD", and at most one smart routing step per route. - The step has no
connection_idand noaction, and itsoutput[]is at most oneAPPROVEDentry. That entry may continue to a fraud step that runs after the payment (which must not route further) or to aCAPTURE/HOLD_FOR_REVIEWstep; declines and errors are handled inside the step. - It must be reachable from step 1. Only fraud, 3DS or authentication steps may lead into it, each through its
APPROVEDorDECLINEDoutputs and routing everynextit has to that same step. - A rule violation is
400 INVALID_ROUTE_CONFIGURATION; a missing cost configuration or an unsupported network token is400withNETWORK_TOKEN_NOT_ONBOARDED/NETWORK_TOKEN_NOT_SUPPORTED.
Percentage splits
Bothstart_split and output[].next_split are lists of { "index", "percentage" } entries:
next_split of [{ "index": 2, "percentage": 70 }, { "index": 3, "percentage": 30 }], roughly 70% of the payments that hit that output continue on step 2 and 30% on step 3; each individual payment follows exactly one branch. Over many payments the traffic converges to the configured percentages.
Rules:
start_splitneeds at least one entry. A single entry withpercentage: 100is the explicit way to send all traffic to one step; omittingstart_splitmeans 100% onindex: 1.next_splitneeds at least two entries. For a single destination usenext.nextis optional next tonext_split; if you send both,nextmust be the first entry ofnext_split. Responses always includenext= first entry alongsidenext_split, so clients that only readnextkeep a fallback.- Every step must be reachable from the entry, through
start_split,nextornext_split. - A
percentageof0is allowed, so you can keep a step in the configuration while it receives no traffic. - Percentages are integers. Decimals are rejected.
- A split that breaks one of these rules is rejected with
400 INVALID_ROUTE_CONFIGURATION;messagesnames the split and the rule. A wrong shape (a decimal percentage, a missingpercentage, a single-entrynext_split) is rejected before that with400 INVALID_PARAMETERS/BAD_REQUEST.
Update a Routing replaces the full configuration, splits included. A condition set sent without
start_split goes back to a single entry on step 1, and an output sent without next_split keeps only the next it declares, so omitting a split is how you remove it. Retrieve a Routing always returns the current start_split and next_split, so a read-modify-write flow keeps them unless you drop them on purpose.What the API does not show
A few things the dashboard can configure have no representation here: theREFUND, DECLINE and END actions (not step actions in the dashboard either), the per-step provider settings (timeout, network token, 3DS exemptions) and the monitors, and an action step placed where the placement rules do not allow it.
- Retrieve a Routing leaves those steps and branches out of the response.
- Update a Routing does not delete them: what the response cannot show is kept exactly as stored, grafted onto the step it hung from, so a retrieve → update round trip keeps the routing as it was. One exception: a currency condition built in the dashboard with an operator other than
EQUALor with several currencies has noAMOUNTform; it reads back as rawCURRENCY_AND_AMOUNTrows and an update that sends them back is rejected with400 INVALID_ROUTE_CONFIGURATION. Edit that condition in the dashboard, or replace it with anAMOUNTcondition on a singlecurrency. The per-step provider settings follow the provider step with the sameprovider_idandconnection_id; if you replace that connection, they go with it. A stored layout the merge cannot re-attach safely (the route enters on a hidden step, an output splits traffic between a hidden and a visible step, or a hidden step continues to a visible provider) is rejected with400 INVALID_ROUTE_CONFIGURATIONand a message that ends with “Edit this routing in the dashboard”. - To change any of those parts, use the dashboard.