Skip to main content

Orchestr.js reference

Orchestr.js is the browser SDK behind card payments. It mounts the secure card fields, exchanges the entered card for a token, confirms the payment, and renders 3-D Secure — while your page never sees a card number.

Install

Always load the SDK from our CDN — never bundle or self-host it. The pinned-major URL means a security fix reaches your payment page without you redeploying, and PCI DSS v4's script-integrity duties (6.4.3, 11.6.1) remain on Orchestr's side:

<script src="https://js.upprove.com/v1/orchestr.js"></script>

For bundlers, @orchestr/card-js is a tiny loader that injects that same tag and gives you full TypeScript types:

npm install @orchestr/card-js
import {loadOrchestr} from '@orchestr/card-js';
const Orchestr = await loadOrchestr();

Orchestr(publishableKey)

Creates a client. The key's prefix selects the environment — a pk_test_ key can never reach production:

Key prefixEnvironment
pk_test_Sandbox — test cards only.
pk_live_Live.

Passing a secret key (sk_…) throws immediately: secret keys must never reach the browser.

MethodDescription
orchestr.elements(options?)A new element group. Accepts {locale}.
orchestr.collectCard(clientSecret)Collect the mounted card, resolve with a token.
orchestr.confirmCardPayment({orderId, token})Confirm the payment; renders 3-D Secure if required.

The card element

const card = orchestr.elements().create('card');
card.mount('#card-element');
await card.ready; // resolves once the secure fields have loaded

One combined element renders the number, expiry, and CVC fields. It lives in an iframe on Orchestr's origin, sized automatically to its content.

MemberDescription
mount(target)Mount into a selector or element. Throws if the target is missing.
unmount()Detach; the element can be mounted again.
destroy()Terminal teardown — release the element and all listeners.
readyPromise resolving when the fields are interactive. Await before enabling Pay.
update({locale})Change display options in place.
clear() / focus() / blur()Field utilities.
on(event, handler) / off(event, handler)Subscribe / unsubscribe.

Events

EventPayloadFires when…
readyThe secure fields have loaded and are interactive.
change{complete, error, fields}Validity changes. Enable your Pay button on complete.
focus / blur{field}A field gains or loses focus.
submittingA collection has started (UX hint — show a spinner).
loaderror{error}The fields failed to load (usually a CSP issue — see below).

collectCard(clientSecret)

Submits the card from inside the secure fields and exchanges it for a durable token. The clientSecret is the next_action.client_secret from your server's POST /v1/payments call — a short-lived grant scoped to that one payment.

The same method also serves the collection leg of a card transfer, where the client secret comes from POST /v1/transfers and the token it mints is payout-scoped rather than charge-scoped. Don't call confirmCardPayment() on that flow — a transfer is settled by your server with POST /v1/transfers/{orderId}/execute.

const {card, error} = await orchestr.collectCard(clientSecret);

Resolves with either card or error, never throws on a decline:

card fieldDescription
tokenThe card token (tok_…). Opaque, non-sensitive — safe to store and send to your server.
brandCard scheme (e.g. visa) — null until identified.
last4 / binDisplay-safe digits.
expMonth / expYearExpiry.

On failure the fields keep their contents so the customer can correct and retry. collectCard is never retried automatically.

confirmCardPayment({orderId, token})

Confirms the payment with the collected token. When the issuer requires 3-D Secure, the SDK renders the challenge in your page and completes the flow — you write no 3DS code.

const {payment, error} = await orchestr.confirmCardPayment({orderId, token});

payment.status mirrors the payment status and can be any of completed, failed, authorized (a manual-capture hold), settling, canceled, or requires_action. Don't branch on completed alone — treat anything that isn't failed as "not yet refused" and wait for the webhook.

Treat the value as a display hint only — the signed payment.* webhooks are the authoritative result, and the only safe trigger for fulfilment.

How the challenge is presented

When 3-D Secure is required, how the SDK mounts the challenge is a per-account setting, surfaced to the SDK as a display_mode of inline, popup, or redirect. redirect navigates the whole window away from your page, so don't rely on your page's JavaScript state surviving the challenge — re-read the payment on return.

display_mode and challenge_url are browser-SDK concerns and never appear on the Merchant API. If you want to render 3-D Secure yourself from your own server, see server-to-server card payments instead.

Errors

Every failure resolves with one shape:

{
"type": "validation_error",
"code": "CLIENT_SECRET_EXPIRED",
"message": "…",
"correlationId": "…"
}
typeMeaning
validation_errorField-level problems, raised before anything leaves the browser.
authentication_errorThe client_secret was rejected or has expired.
api_errorOrchestr failed to process the request.
network_errorThe request never reached Orchestr.
integration_errorDeveloper misuse — these throw instead of resolving, and always mean a bug in the integration.

Branch on type, key your customer-facing copy off code, and quote correlationId in support tickets. A client_secret lives 15 minutes; an expired one fails fast with CLIENT_SECRET_EXPIRED — create a new payment to mint a fresh one.

Content-Security-Policy

If your page sets a CSP, allow the SDK script, the secure-fields frame, and the confirm call:

DirectiveLiveSandbox
script-srchttps://js.upprove.comhttps://js.upprove.com
frame-srchttps://fields.card.upprove.comhttps://fields.sandbox.card.upprove.com
connect-srchttps://api.upprove.comhttps://api.sandbox.upprove.com

A missing frame-src is the usual cause of a loaderror with code IFRAME_BLOCKED.

Using with React

No bindings package is needed — mount in an effect and destroy on unmount:

function CardField({orchestr, onReady}) {
const ref = useRef(null);

useEffect(() => {
const card = orchestr.elements().create('card');
card.mount(ref.current);
card.ready.then(onReady, () => {});
return () => card.destroy(); // required: React 18 StrictMode mounts twice
}, []);

return <div ref={ref} />;
}

Next steps

  • Card payments — the end-to-end integration guide.
  • Webhooks — fulfil on payment.succeeded, never on the browser result.