condition_sets[].conditions[] are combined with logical AND. For OR semantics, split into multiple condition sets ordered by sort_number.
condition_type catalog
conditional operators
LESS_OR_EQUAL_THAN does not apply to any condition_type in the table above — it is used only by
VOLUME_PAYMENTS_LIMIT, which carries its own threshold semantics rather than the generic numeric
comparison, so do not read a plain <= into it. That condition type is not documented on this page
yet, so treat the table above as the common set, not the complete one.
CONTAINS is a substring test for METADATA, which is the type this page documents for it. Other
condition types may implement it differently — ADDITIONAL_FIELD, for one, compares values[0] for
equality rather than containment — so do not carry the substring semantics across types.
The Rejected at save time column is the value count only. A yes means
POST/PUT returns 400 when the count does not match, naming the condition type and operator.
A no means the count is not checked at save time, and what a wrong count does at evaluation
depends on the operator — do not rely on it being harmless.
Where enforcement applies it is exact, not a minimum: a surplus value is rejected just as a
missing one is. BETWEEN with ["0", "60", "EUR"] is a 400, not a silently truncated range.
A value count already stored on a routing version is kept. If a version holds a condition whose
count predates this check, saving that version again does not fail on it — only a newly introduced
wrong count is rejected. This also holds for a version duplicated from such a source.
Card brands
CARD_BRAND accepts the values below. A value outside the list is rejected at save time with
400 INVALID_CARD_BRAND, naming the offending value. The list is validated against two internal
sources at save time, so a newly supported scheme may be accepted before it appears here.
Special cases
AMOUNTrequirescurrency. Comparisons are FX-naive; only payments whose currency matches the rule’scurrencyare evaluated.METADATArequireskey. Comparespayment.metadata[key]. If the key is absent on the payment (or the payment has nometadata), the condition does not match, whatever the operator. This includes the negative operators: a payment without the key does not matchNOT_EQUALorNOT_ONE_OFeither. See the note below for how to route payments that don’t carry the key.- Card-only condition types (
CARD_ISSUER_COUNTRY,CARD_TYPE,CARD_BRAND,CARD_BIN) are only valid whenpayment_method = "CARD". COUNTRYvsCARD_ISSUER_COUNTRY. The two are sourced independently:COUNTRYmatches the transaction country your backend submits in the payment request, whileCARD_ISSUER_COUNTRYmatches the issuer country Yuno’s own BIN lookup derives from the card number. The same payment can beCOUNTRY = USandCARD_ISSUER_COUNTRY = GBat once. The BIN lookup runs before a provider is selected, is identical in sandbox and production, and reflects real-world BIN-registry data — never the processor’s view of the card.- Not to be confused with Communications Campaigns. That product has its own rule engine, where
AMOUNT_AND_CURRENCYwithBETWEENtakes three values["min", "max", "currency"]. Routing’sAMOUNTtakes two values plus a siblingcurrency, and a third value is rejected. CARD_BINwithBETWEENexpresses an issuer range and is validated more strictly than the generic two-value rule: exactly two values, both the same length, that length either 6 or 8, all digits, and the first less than or equal to the second. Anything else is400 INVALID_ROUTE_CONFIGURATION— so["411111", "41111111"](mismatched lengths) and["500000", "400000"](descending) are both rejected. Unlike every other condition type, a storedCARD_BIN BETWEENis not grandfathered: a version holding a malformed one is rejected on every subsequent save until it is corrected.- Numeric values are submitted as strings to match the
values: string[]schema. Yuno parses them based on thecondition_type.
Routing payments that don’t carry a metadata keyBecause a missing key never matches, a rule such as
METADATA QA NOT_EQUAL "true" skips every payment that has no QA key. To split traffic by the presence of a key, match the payments that do carry it, and let everything else fall through:- Put a condition set with
METADATAQAEQUAL"true"first (lowersort_number). - Put the condition set for all other payments after it, without a
METADATAcondition onQA.
QA = "true" match the first set; payments without the key, or with any other value, reach the second.Testing CARD_ISSUER_COUNTRY rules in sandbox
Two examples with Stripe’s test cards:
To verify a
CARD_ISSUER_COUNTRY rule end-to-end today, work with resolved values rather than documented ones — the lookup is deterministic:
- Run one sandbox payment with a candidate test card.
- Read
card_data.country_codefrom the payment (payment details in the dashboard, or the Retrieve Payment response). - Build the rule against that value. For example,
4242 4242 4242 4242is a dependableGBcard end-to-end.
CARD_TYPE, CARD_BRAND), though country is where provider test-card documentation diverges most often.