Skip to main content
A routing tells Yuno, for one 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

Top-level fields
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
TIMEOUT and ERROR_RATE appeared in earlier versions of this page. They are not members of the status enum: sending either one rejects the whole routing with 400, and messages lists the allowed values. A provider timeout is handled by INTERNAL_ERROR.

Provider step kinds

The kind of a provider step is derived from its provider_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:
Responses return 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
  1. The route enters at index: 1, unless start_split is set — then Yuno draws one entry step per payment according to the percentages. If the entry step is a CANCEL step, the payment is rejected and the route ends.
  2. The provider call runs.
  3. Yuno walks output[] top-to-bottom; the first entry whose status (plus the group predicate on DECLINE_GROUP, MAC_CODE_GROUP and SUCCEEDED_GROUP) matches the outcome wins. An entry with retry: true runs the same provider once more first; the outcome of that second attempt decides.
  4. If the matched entry has next, jump to that step. If it has next_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.
  5. 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 by group_id.
Rules:
  • group_id must be a group of the routing’s account and of the kind the status expects. An unknown id, an id of another account, or a Merchant Advice Code group sent as DECLINE_GROUP is rejected with 400 INVALID_ROUTE_CONFIGURATION; messages names the group_id and the kind it actually is.
  • DECLINE_GROUP with decline_types[] and no group_id keeps working as before: Yuno creates a decline group named auto_… with those sub-statuses on every save. Prefer group_id when the group already exists, so the account does not accumulate automatic groups.
  • DECLINE_GROUP with both group_id and decline_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_GROUP and SUCCEEDED_GROUP require group_id; SUCCEEDED_GROUP does not accept decline_types[]. Create those groups in the dashboard first.
  • The same group_id cannot appear twice in the output[] of one step.
  • Responses return group_id and group_name on every group entry, and decline_types[] on DECLINE_GROUP and MAC_CODE_GROUP entries, 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: true on APPROVED, MAC_CODE_GROUP or SUCCEEDED_GROUP is rejected with 400 INVALID_ROUTE_CONFIGURATION; retry: false is accepted anywhere, which is what lets you send a retrieved routing back unchanged.
  • Responses always return retry on every entry (false when not set), so you can see which branches retry.
  • On Update a Routing, an entry sent without retry keeps the value already stored for that position; send retry: false explicitly to turn a retry off.

Action steps

An action step ends the route with an action instead of calling a provider. It has index 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).
A step that breaks these placement rules is rejected with 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. Unlike CAPTURE 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.
Rules, the same the dashboard applies:
  • Only on routings with payment_method = "CARD", and at most one smart routing step per route.
  • The step has no connection_id and no action, and its output[] is at most one APPROVED entry. That entry may continue to a fraud step that runs after the payment (which must not route further) or to a CAPTURE / HOLD_FOR_REVIEW step; 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 APPROVED or DECLINED outputs and routing every next it has to that same step.
  • A rule violation is 400 INVALID_ROUTE_CONFIGURATION; a missing cost configuration or an unsupported network token is 400 with NETWORK_TOKEN_NOT_ONBOARDED / NETWORK_TOKEN_NOT_SUPPORTED.
Responses return the step in the same shape. On update the request replaces the step; it is not kept when left out.

Percentage splits

Both start_split and output[].next_split are lists of { "index", "percentage" } entries:
How a split is resolved: the split is evaluated once per payment, before the step runs. For a 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_split needs at least one entry. A single entry with percentage: 100 is the explicit way to send all traffic to one step; omitting start_split means 100% on index: 1.
  • next_split needs at least two entries. For a single destination use next. next is optional next to next_split; if you send both, next must be the first entry of next_split. Responses always include next = first entry alongside next_split, so clients that only read next keep a fallback.
  • Every step must be reachable from the entry, through start_split, next or next_split.
  • A percentage of 0 is 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; messages names the split and the rule. A wrong shape (a decimal percentage, a missing percentage, a single-entry next_split) is rejected before that with 400 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: the REFUND, 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 EQUAL or with several currencies has no AMOUNT form; it reads back as raw CURRENCY_AND_AMOUNT rows and an update that sends them back is rejected with 400 INVALID_ROUTE_CONFIGURATION. Edit that condition in the dashboard, or replace it with an AMOUNT condition on a single currency. The per-step provider settings follow the provider step with the same provider_id and connection_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 with 400 INVALID_ROUTE_CONFIGURATION and a message that ends with “Edit this routing in the dashboard”.
  • To change any of those parts, use the dashboard.