Base URL
https://api.symphony.io/v1
Endpoints
18 documented routes
Symphony is an intelligent payment acquirer routing engine built by PayIntelli. It evaluates every payment transaction in real time, scores all available payment providers simultaneously, and returns a ranked list of providers — best to worst — for the calling system to route through in order.
The goal of Symphony is simple to state but complex to execute: send each transaction to the acquirer most likely to approve it, at the lowest cost, while keeping the business's contractual volume commitments to each acquirer on track.
Symphony replaces static routing rules — route VISA cards to provider A, European cards to provider B — with a dynamic, data-informed decision that accounts for the actual characteristics of the transaction in front of it. Every routing decision considers three things simultaneously: which acquirer is most likely to succeed with this specific transaction, which acquirer will cost the least to process it, and which acquirers have unfulfilled volume obligations that the business needs to meet by the end of the month.
The calling system receives an ordered list of provider IDs and works through them in sequence — trying the top-ranked provider first, and falling back to the next if that provider declines or is unavailable. Symphony provides the recommendation. The calling system retains control.
Example scenario: A customer submits a €33 VISA debit payment from a French IP address at 10:30am on a Tuesday morning. Symphony evaluates all four active providers against this transaction simultaneously. One provider has a historically high success rate for European VISA debit transactions in this amount range. A second provider has a lower success rate but a lower processing fee. A third provider has already fulfilled 99% of its monthly volume obligation and should not receive more traffic this month. The fourth provider is currently deprioritised due to an active routing rule applied by the operations team following reported gateway issues in Europe. Symphony scores all four and returns them ranked: Provider 1, Provider 2, Provider 4, Provider 3 — with Provider 3 at the bottom because its contract is nearly full, and Provider 4 at position three rather than blocked outright because falling back to it is still better than no acquirer at all.
Any business processing payments through more than one acquirer faces a routing problem. Every transaction has to go somewhere, and that choice — made thousands or millions of times a day — has a significant cumulative impact on authorisation rates, processing costs, and commercial relationships.
Most businesses today solve this problem poorly, or not at all.
2. The Problem We Solve
Description
The most common approach to multi-acquirer routing is a static rule table. An engineer writes logic: if the card brand is VISA, route to provider A. If the transaction is in EUR, route to provider B. If the amount is above £500, try provider C first. These rules are simple to understand, easy to audit, and quick to implement.
They are also deeply limited.
Static rules cannot respond to changing provider performance. If provider A begins declining a certain class of European cards at an elevated rate — because of a gateway issue, a change in their risk policies, or a temporary technical problem — a static rule that sends all VISA transactions to provider A will continue doing so, racking up declines and failed customer experiences, until an engineer manually updates the rule. That manual response loop takes time. During that window, the business is losing authorisations.
Static rules cannot optimise for cost. A routing decision that maximises authorisation rate may not minimise processing fees, and vice versa. Balancing these two objectives simultaneously within a rule system requires complex, nested conditions that become increasingly fragile as the number of providers grows. Most businesses simply do not attempt it, and leave cost savings on the table as a result.
Static rules cannot track contract fulfilment. Most acquirer relationships involve volume commitments — the merchant agrees to route a minimum number of transactions per month through a given provider. If the routing rules do not account for how close each provider is to its monthly target, the business may arrive at the end of the month having under-served one provider's commitment and over-served another's. This creates commercial friction, renegotiation costs, and in some cases financial penalties.
And static rules require ongoing maintenance. Every time a new provider is added, every time a provider's performance changes, every time a commercial agreement is updated, the rules need to be reviewed and potentially rewritten. This creates a permanent engineering dependency on the business's ability to route payments intelligently.
2. The Problem We Solve
Description
The impact of poor routing decisions compounds quickly at scale. Consider a business processing 50,000 transactions per day across four acquirers.
If routing decisions result in 1% more declines than optimal — because transactions are being sent to acquirers that are statistically less likely to approve them — that is 500 unnecessary declined transactions per day. Each declined transaction is a lost sale, a frustrated customer, and potentially a customer who does not return. Over a month, that is 15,000 lost conversions.
If routing decisions ignore fee differences between providers — where the cheapest provider charges 1.4% and the most expensive charges 1.9% on the same transaction — and the business routes evenly rather than preferring the cheaper provider, the excess cost on €5 million of monthly volume is €25,000 per month, or €300,000 per year.
These are not edge cases. They are the normal operating cost of routing without intelligence.
2. The Problem We Solve
Description
There are commercial routing optimisation tools available from specialist vendors. These products face the same fundamental problem as third-party fraud tools: they are black boxes trained on industry-wide data, with limited ability to incorporate the specific commercial relationships, contract structures, and provider dynamics of a particular business.
They also add an external dependency to a highly sensitive, latency-critical flow. Payment routing happens in the window of a live authorisation. Adding a third-party API call to that flow introduces latency, availability risk, and a vendor dependency that compounds the operational complexity of the payment stack.
Symphony is built to avoid all of these problems. It is in-house infrastructure, trained on real transaction data from the PayIntelli platform, incorporating the actual commercial structure of each client's acquirer relationships, and operating within the authorisation window without adding external dependencies.
At a high level, every Symphony routing decision follows this flow:
Payment system receives a transaction from a customer
↓
Symphony API receives the transaction details
↓
API key is validated — unauthorised requests are rejected immediately
↓
Active providers are loaded for this client:
→ Only providers with an active contract for this client are considered
→ Providers marked inactive in the system are excluded
→ Per-client exclusion overrides are applied if configured
↓
Contract states are loaded for each provider:
→ Monthly volume obligation for this client-provider pair
→ Month-to-date successful transaction count for this client-provider pair
→ Fill percentage = MTD successes ÷ obligation
↓
Active routing rules are loaded:
→ BLOCK rules that match this transaction's region and payment method
→ Rules are checked for expiry; expired rules are ignored
→ Rules are filtered to applicable layers (region-level, method-level, provider-level)
↓
Transaction features are extracted from the payload:
→ Amount, currency, USD equivalent
→ Timestamp signals (hour, day, week, weekend, month)
→ Identity signals (email, name, email-name consistency)
→ Card signals (credit / debit / prepaid)
→ Geography signals (country, domestic vs. foreign)
→ Network signals (IP address indicators)
→ Payment method (VISA, MC, AMEX, etc.)
→ Authentication signals (SCA, exemptions)
→ Address signals (postal code, city, state)
↓
All provider models are invoked in parallel:
For each active provider:
→ Success probability: how likely is this acquirer to approve this transaction?
→ Estimated cost (IC++): what is the expected interchange-plus fee for this transaction?
↓
Composite score is calculated for each provider:
→ Contract component: how much volume capacity does this provider still have?
→ Success component: weighted contribution from success probability
→ Cost component: weighted contribution from fee efficiency
→ Final score = combined prediction × contract capacity remaining
↓
Routing rules are applied:
→ Providers matched by BLOCK rules are demoted to the end of the list
→ Non-blocked providers are ranked by composite score with weighted randomisation
↓
Usage is metered: one unit recorded per call
↓
Response returned to calling system:
{ "providers": [<ranked provider IDs, best to worst>] }
↓
Calling system attempts providers in ranked order
The entire flow — from receiving the request to returning a ranked list — is designed to complete within the latency window of a live payment authorisation. All provider models are invoked in parallel to minimise total evaluation time. Symphony enforces an internal time budget; if the budget elapses before all providers have responded, the results received so far are used to construct the ranking.
4. Core Capabilities
Description
The primary output of Symphony is a ranked list of provider IDs, ordered from most recommended to least recommended for the specific transaction at hand.
This ranking is not static. The same transaction submitted at different points in the month may produce a different ranking — because contract fill levels change as transactions are processed, because routing rules may be active at one time and not another, and because the underlying models incorporate timing signals that capture time-of-day and day-of-week performance patterns.
The calling system is expected to attempt providers in the order Symphony provides. If the top-ranked provider declines or is unavailable, the system falls back to the second-ranked provider, then the third, and so on. Symphony ensures there is always a fallback — providers are demoted, not removed.
4. Core Capabilities
Description
For each provider, Symphony estimates the probability that the provider will successfully authorise the transaction. This is a per-provider, per-transaction estimate — not a static performance metric. It accounts for the specific characteristics of the transaction: the amount, the payment method, the card type, the geography, the time of day, and a range of other signals.
Success probability is the primary driver of routing quality. A provider with a high expected success rate for a given transaction gets a higher ranking than one with a lower expected rate, all else being equal.
Success probability estimates are produced by models trained on historical transaction outcomes on the PayIntelli platform. The models learn, from real authorisation history, which transaction characteristics are associated with approvals and which are associated with declines, for each specific acquirer. This means the estimates reflect not just general acquirer performance, but acquirer performance in the context of the specific transaction types that flow through the platform.
4. Core Capabilities
Description
Processing costs — interchange, scheme fees, and gateway fees — vary by acquirer and by transaction. These fees are not always visible at the point of routing, but they accumulate into a significant cost line for high-volume businesses.
Symphony incorporates estimated processing cost into its routing score. All else being equal, Symphony prefers the provider that will cost less to process the transaction. This preference is weighted — it does not override a large difference in success probability — but it consistently nudges routing toward lower-cost providers at the margin.
The cost component of the routing score uses a fee normaliser that converts the absolute fee estimate into a comparative score. A provider expected to charge a very low fee scores full marks on the cost dimension. A provider expected to charge near the maximum plausible fee scores zero. Most providers fall somewhere in between.
When a provider's model does not produce a reliable cost estimate — because the provider has insufficient fee data in the training set — Symphony falls back to a pre-configured default cost estimate for that provider. This ensures the cost component remains meaningful even when model data is sparse.
4. Core Capabilities
Description
Most acquirer relationships are governed by commercial agreements that include minimum volume commitments. A merchant may agree to route a minimum of 10,000 successful transactions per month through a given provider in exchange for favourable fee terms. Failing to meet that commitment by the end of the month creates commercial problems. Over-routing beyond what is needed wastes volume that could fulfil other commitments.
Symphony tracks each provider's monthly contract fulfilment in real time. At the start of each routing decision, Symphony looks up how many successful transactions have already been routed to each provider this month for this client, and compares that to the contracted monthly obligation.
A provider that has fulfilled only 20% of its monthly obligation gets strong positive weighting — Symphony actively steers volume toward it to catch up. A provider that has fulfilled 80% of its obligation gets moderate weighting. A provider that has fulfilled 99% or more of its obligation is nearly shut off — it receives a fraction of the weight it would otherwise get — because sending more volume to it does not serve the business's commercial interests.
This mechanism operates continuously throughout the month, not just at month-end. As the month progresses and fill levels change with each transaction routed, the routing weights adjust dynamically. No manual intervention is required to rebalance traffic toward under-served providers.
The contract tracking is per client and per provider pair. If a client has not entered into a contract with a provider, that provider is either excluded from routing or receives neutral weighting, depending on configuration.
4. Core Capabilities
Description
Payment providers experience incidents. Gateway failures, elevated decline rates for specific card types, regional connectivity problems, and regulatory holds can all affect a provider's ability to process transactions effectively. When these incidents occur, it is important to reduce or stop routing traffic to the affected provider quickly — before the business accumulates avoidable declines.
Symphony includes a rules engine for exactly this purpose. Operations teams can insert routing rules into the system that cause specific providers to be deprioritised — demoted to the bottom of the ranking — for specific transaction types or geographic regions, for a defined time period or indefinitely.
Rules operate at three levels:
Rules take effect immediately — there is no deployment, no code change, and no Lambda restart required. They are loaded fresh at the start of every routing decision. When the incident is resolved, the rule is deleted or marked inactive, and traffic resumes to the provider on the next request.
Importantly, routing rules do not remove providers from the ranking entirely. Demoted providers appear at the bottom of the list. This means that if all higher-ranked providers fail (which might happen if the incident is widespread), the system can still fall back to the demoted provider. Symphony provides a safety net rather than a hard block.
4. Core Capabilities
Description
Symphony only recommends providers that the client has an active commercial relationship with. At the start of every routing decision, Symphony loads the set of active providers for the client from the contracts table.
If a client has contracts with four providers, only those four providers are considered — even if there are more active providers on the platform. A new provider cannot receive traffic from a client until a contract has been established.
If no contracts are found for a client — which may happen during initial onboarding — Symphony falls back to offering all active providers on the platform. This ensures that routing continues to function while commercial onboarding is completed, rather than failing entirely.
If contracts exist but none of the contracted providers are currently active in the system, Symphony logs a warning and falls back to all active providers, rather than returning an error. Routing continuity is prioritised.
4. Core Capabilities
Description
Provider model invocations can fail. A model may not respond within the time budget. A SageMaker endpoint may experience a transient error. A network timeout may prevent a response from arriving.
Symphony is designed to handle these failures gracefully. Failed provider invocations do not cause the routing request to fail. They are collected in a failures list that is appended to the response alongside the ranking. The calling system can inspect this list for diagnostics but does not need to act on it — a partial ranking is still a valid routing recommendation.
Symphony enforces a time budget across all parallel model invocations. If the budget elapses before all providers have responded, Symphony uses the results collected so far. Any providers that did not respond in time are absent from the ranking. Callers should be aware that in high-latency conditions, the ranked list may be shorter than the total number of active providers.
If all provider invocations fail — no response is received from any provider within the time budget — Symphony returns an error rather than an empty ranking. An empty ranking would be worse than an error, because a calling system might interpret it as "no providers available" rather than "an error occurred."
Integrating Symphony into a payment flow is straightforward. At the point of payment initiation — before the first authorisation attempt is sent to any acquirer — the client sends the transaction details to Symphony and receives back a ranked list of provider IDs.
Step 1 — Call the Symphony API
The client system sends a POST request with the transaction payload. The payload should include as many transaction details as available: amount, currency, payment method, card type, customer geography, and any authentication details. Fields that are not available can be omitted — Symphony handles missing data gracefully.
Step 2 — Receive the ranked list
Symphony returns a JSON response containing an array of provider IDs in ranked order:
Provider ID 3 is the recommended first choice. Provider ID 1 is the fallback. Providers 5 and 4 are further fallbacks, in that order.
Step 3 — Attempt providers in sequence
The calling system sends the authorisation request to the provider identified by the first ID in the list. If the authorisation succeeds, the transaction completes. If the provider declines or is unavailable, the system moves to the next provider in the list, and so on.
Step 4 — Record the outcome
The outcome of each provider attempt — whether it succeeded or failed — is recorded in the platform's transaction history. This data feeds back into Symphony's training cycle, keeping the model's success probability estimates current.
This integration pattern requires no changes to the customer-facing payment experience. It is entirely a back-end routing optimisation. Customers see no difference in how payments are submitted. The routing logic runs transparently between the customer submitting a payment and the acquirer receiving the authorisation request.
6. Security & Compliance
Description
Every request to Symphony must include a valid API key scoped to the Symphony product. Requests without a key are rejected with HTTP 401 before any processing begins. Requests with an invalid key are rejected with HTTP 403. No transaction data is processed and no provider models are invoked for unauthenticated requests.
6. Security & Compliance
Description
Routing decisions are computed entirely in isolation. Each API call loads only the providers and contracts associated with the requesting client. The transaction payload of one client is never visible to or combined with data from any other client. Contract states, routing rules, and provider rankings are scoped to the requesting client throughout the evaluation.
6. Security & Compliance
Description
All communication between the calling system and Symphony uses encrypted connections. Database connections used internally for contract state and routing rule lookups also enforce encryption in transit. Transaction data is never transmitted or queried in plaintext.
6. Security & Compliance
Description
Database credentials used internally by Symphony are not embedded in code or configuration files. They are retrieved at Lambda cold-start from a centralised secrets management service and held in memory only. They are never logged, returned in error responses, or written to any external system.
Symphony records one unit of usage against the calling client's account for every routing request, regardless of how many providers are in the ranked response or whether any provider subsequently succeeds.
Usage recording is asynchronous — it is dispatched to an internal messaging queue after the routing response is assembled. Metering does not add latency to the routing decision.
Usage data is available to the PayIntelli operations and account management teams for billing, capacity planning, and client reporting. Clients can request usage summaries through their account management contact.
8. Observability & Operations
Description
All Symphony evaluations produce structured log entries. Key events logged include:
Logs are written to centralised log storage and are available to the PayIntelli operations team for real-time monitoring and historical analysis.
8. Observability & Operations
Description
Routing rules are the primary operational control surface for Symphony. The operations team can insert, modify, or deactivate routing rules at any time without requiring a code deployment or Lambda restart. Rules take effect on the next routing request received after insertion.
When investigating an incident or debugging unexpected routing behaviour, the operations team can inspect the active routing rules table to understand which providers are currently subject to BLOCK rules, what their scope is, and when they were created.
8. Observability & Operations
Description
Each provider model is invoked independently and independently can fail. Symphony logs all provider model invocations, including whether they succeeded, how long they took, and what prediction values they returned. If a specific provider model is failing consistently — returning errors on every invocation — this will be visible in the logs and can be investigated without affecting the rest of Symphony's operation.
8. Observability & Operations
Description
Symphony's underlying infrastructure — the SageMaker Multi-Model Endpoint hosting all provider models — is a managed, persistent service. It does not require per-request provisioning. Symphony monitors for endpoint availability and retries failed invocations once with exponential backoff before marking a provider as failed for that request.
| Version | Date | Milestone |
|---|---|---|
| 0.1.0 | August 2025 | Initial prototype: basic multi-provider scoring with success probability; static IC++ defaults; no contract tracking |
| 0.5.0 | October 2025 | Contract fulfilment tracking integrated; month-to-date fill percentage incorporated into scoring; provider filtering by contract |
| 1.0.0 | May 2026 | Full production release: parallel model invocation with time budget; L1/L2/L3 routing rules engine; weighted random ranking with configurable power parameter; provider ID-based slugs aligned with training artifacts; IC++ fallback defaults per provider; comprehensive structured logging; API key authentication scoped to Symphony product; SQS usage metering |
| 1.0.1 | June 2026 | Contract state DB connection lifecycle fix; routing rule expiry enforced at load time; max routing rules configurable via environment; provider exclusion via environment variables (SKIP_PROVIDER_SLUGS, SKIP_PROVIDER_IDS) |
To set accurate expectations:
Symphony is not a payment gateway. Symphony decides which provider to use — it does not communicate with providers, submit authorisation requests, or handle responses. It is a routing layer that sits before the gateway interaction.
Symphony is not a guarantee of authorisation. A high ranking for a provider means Symphony estimates a higher probability of success — not a certainty. Declines can occur for many reasons outside Symphony's scope, including card limits, fraud blocks applied by the issuer, and gateway outages that begin after the routing decision.
Symphony is not a contract management tool. Symphony reads contract obligations to inform routing weights. It does not create, modify, or validate contracts. Contract records must be maintained by the operations and commercial teams through their normal processes.
Symphony is not a fraud detection system. Symphony does not evaluate whether a transaction is fraudulent. It evaluates which acquirer is most likely to approve and cheapest to use. Fraud detection is the responsibility of Shield, which should be called independently before or alongside Symphony in the payment flow.
Symphony is not a real-time dashboard. Symphony does not provide a client-facing interface for viewing routing decisions, provider rankings, or fill levels. These are available through log access and reporting tools operated by the PayIntelli team.
Symphony is not a load balancer. Symphony's weighted randomisation introduces some routing diversity among top-ranked providers, but it is not designed to distribute load evenly across providers. Its objective is routing quality — maximising authorisation rate and minimising cost — not load distribution.
Symphony is not a static system. The routing rankings it produces will change over time as contract fill levels change, as routing rules are added and removed, and as new model versions are trained. Clients should not expect identical rankings for identical transactions across different time periods.