GET /checkout/:shopUrl/payment-intent-resolver is the public endpoint the
checkout-spa calls on page load to determine which payment methods to render. It does
not require a JWT — shopUrl is the only input, and the response is safe to expose
publicly because it contains only payment-method capabilities, never customer state or
secrets.
This endpoint is public — no JWT, no IpAllowlistGuard, no GeoBlockGuard. It is rate-limited
per IP via the standard public-endpoint policy (60 req/min/IP). Cached at the CDN for 60s
keyed on
shopUrl.When to use
Call this once at checkout page load to know which payment renderer to mount. The response tells the FE:- Which card processor to use (Stripe / Telr / Paymob / Bonum / null) + the right
publishableKey - Whether to show PayPal
- Whether to show crypto (Coinbase Commerce)
- Whether to show wallet (Apple Pay / Google Pay tokens — routed through Bonum or Stripe depending on the merchant config)
- The merchant’s checkout
currency - Resolver
meta— the source-of-truth chain the resolver walked (useful for debugging “why am I seeing Stripe instead of Telr?”)
Source-of-truth resolution chain
The resolver walks the following sources in order, returning the first non-null match per payment method:shopPaymentMethodsV2
The merchant’s explicit per-shop payment-method config. If a method is explicitly
disabled here, it short-circuits — later sources cannot re-enable it.
Partnership preset (when #1575 lands per-merchant config)
If the merchant belongs to a partnership (e.g.
shopsadiq-telr-gcc), the preset’s
default card processor is applied. Currently in active rollout — once #1575 fully lands
per-merchant config, this step becomes the canonical source for partnership merchants.KYB cohort
The merchant’s
kybCohort (one of 8 enum values) drives the regional default — e.g.
GCC cohorts default to Telr, Mongolia cohorts default to Bonum, US cohorts default to
Stripe.PSP breaker
If the candidate PSP’s circuit breaker is
open, the resolver falls through to the
next viable option. The skipped PSP is recorded in meta.skippedByBreaker[].meta field of the response, so a FE engineer can
inspect a single response and understand exactly why a given renderer was chosen.
GET /checkout/:shopUrl/payment-intent-resolver
Authentication
None — public endpoint. Rate-limited per IP (60 req/min).Path parameters
| Param | Type | Required | Description |
|---|---|---|---|
shopUrl | string | Yes | The shop’s subdomain (e.g. unstoppable for unstoppable.droplinked.io) |
Response — 200 OK
Field reference
card — primary card renderer (or null if no card processor is wired)
| Field | Type | Description |
|---|---|---|
provider | enum (stripe | telr | paymob | bonum) | Which PSP processes the card payment |
label | string | Human-readable label for the renderer (“Card”, “Credit/Debit Card”) |
accountId | string | The PSP-side account / terminal / merchant ID — informational only |
renderer | enum (stripe-elements | telr-hosted | paymob-iframe | bonum-hosted) | Which renderer component the FE should mount |
publishableKey | string | null | The PSP’s client-side publishable key. null when the renderer is hosted-only (Telr, Bonum) |
paypal
| Field | Type | Description |
|---|---|---|
enabled | boolean | Whether to show the PayPal button |
clientId | string | null | PayPal client ID for the JS SDK |
currency | string | Three-letter ISO currency for the PayPal order |
intent | enum (capture | authorize) | PayPal intent mode |
crypto
| Field | Type | Description |
|---|---|---|
enabled | boolean | Whether to show the crypto-pay option |
provider | enum (coinbase) | null | Crypto processor; only coinbase is currently wired |
wallet
| Field | Type | Description |
|---|---|---|
applePay | boolean | Whether to render Apple Pay |
googlePay | boolean | Whether to render Google Pay |
tokenProvider | enum (stripe | telr | bonum) | Which PSP consumes the wallet token |
currency
The merchant’s checkout currency. Format three-letter ISO 4217 (USD, AED, MNT, EUR).
meta
Informational only — not consumed by the renderer. Captures kybCohort, partnership,
the full resolution chain, and any PSPs skipped because their breaker was open.
Response — 200 OK with no card processor
Error responses
| Status | When |
|---|---|
404 | shopUrl does not resolve to an active shop |
410 | Shop exists but is suspended / archived |
429 | Rate limit exceeded for caller IP |
Example
JavaScript example
Debugging
When the FE renders the wrong processor (e.g. Stripe when you expected Telr), inspect themeta.chain field — it explains exactly which step resolved the card processor. The most
common reasons for an unexpected provider are:
| Symptom | Likely cause |
|---|---|
| Stripe rendered for a GCC merchant | shopPaymentMethodsV2 has an explicit Stripe override; remove it |
card: null for a merchant that has Telr wired | Telr breaker is open — check PSP health |
card.publishableKey: null but renderer is stripe-elements | The per-merchant Stripe config is missing the publishable key — re-write via aggregate provisioner |
Related
- Bonum admin — per-merchant Bonum config (affects
wallet.tokenProvider). - Telr admin — Telr reconcile (does not affect resolver output directly, but breaker state does).
- PSP health — breaker state for every PSP the resolver consults.
- Aggregate merchant provisioner — partnership-preset writes that drive resolver defaults.