Merchant Managed
This guide provides enterprise merchants with a comprehensive integration path for Forter's Orchestration service, enabling unified payment processing with built-in fraud protection, predictive routing, and 3DS handling. The Orchestration API consolidates multiple payment operations into a single, cohesive workflow that replaces traditional PSP-specific integrations while maintaining enterprise-grade reliability and performance.
Integration Flow
flowchart TD
A["Customer enters card details"] --> B["Phase 1: Hosted Fields Tokenization"]
B --> C["Phase 2: Pre-Authorization Fraud Check"]
C --> D{"Fraud Decision"}
D -- Decline --> E["Reject Transaction"]
D -- "Managed Order Token" --> F["Execute 3DS"]
D -- Approve --> G["Phase 3: Create Payment"]
F --> H["Handle 3DS Challenge"]
H --> I{"Challenge Success?"}
I -- No --> E
I -- Yes --> G
G --> L["Phase 4: Capture Payment"]Phase 1: Hosted Fields Integration (Tokenization)
Securely capture payment credentials using Forter's Hosted Fields, replacing PSP-native checkout fields.
1.1 Backend Session Key Generation
Generate an authentication token for the frontend to initialize Hosted Fields.
Endpoint: POST /v1/tokenization/client-key
// Node.js example
router.get('/client-key', async (req, res) => {
const authString = Buffer.from(
`${FORTER_SITE_ID}:${FORTER_SITE_SECRET}`
).toString('base64')
const authorization = `Basic ${authString}`
const response = await axios({
method: 'POST',
url: `${baseUrl}/v1/tokenization/client-key`,
headers: {
Authorization: authorization,
'Content-Type': 'application/json',
},
data: { ttlMinutes: 60 },
})
res.json({ token: response.data.clientKey })
})1.2 Frontend SDK Initialization
Include Forter's SDK on your checkout page:
<script
type="text/javascript"
data-site-id="YOUR_SITE_ID"
id="checkoutTools__script"
src="https://sdk.checkouttools.com/v1.2/collect.js">
</script>Initialize and configure Hosted Fields:
const forterCollect = await window.checkoutTools.collect.init({
environment: 'production',
authToken: await getAuthToken(),
onValidityChange: (fieldId, isValid, error) =>
updateFieldValidation(fieldId, isValid, error),
onCardBrandChange: (cardBrand) => updateCardBrandDisplay(cardBrand),
})
await forterCollect.addFields({
'card-holder-name': {
type: 'CARD_HOLDER_NAME',
placeholder: 'Name on card',
style: getFieldStyles(),
},
'card-number': {
type: 'CARD_NUMBER',
placeholder: '1234 5678 9012 3456',
style: getFieldStyles(),
},
'card-expiry': {
type: 'CARD_EXPIRATION_DATE',
placeholder: 'MM/YY',
style: getFieldStyles(),
},
'card-cvc': {
type: 'CARD_CVC',
placeholder: 'CVC',
style: getFieldStyles(),
}
})1.3 Token Submission
const handlePaymentSubmit = async (formData) => {
const tokenResult = await forterCollect.submit();
if (!tokenResult.success) {
handleValidationErrors(tokenResult.errors);
return;
}
await processPayment({ ...formData, forterToken: tokenResult.token });
};1.3.1 Upgrade Token (Optional)
If you need to store the payment method and/or provision a network token for it, you must use the /upgrade endpoint.
Calling this endpoint creates a new multi-use token and invalidates the existing single-use token along with its CVC. You can also choose to provision a network token during the upgrade, allowing Forter to use it later during authorization.
Example Request
{
"token": "ftr1d8a56cfa6b3745a39e4a42d5ab1048c8",
"networkToken": {
"provision": true
}
}Example Response
{
"token": "ftr1efsdfew54wetg54ugdn58ns0482ko",
"networkTokenStatus": {
"created": true
}
}Phase 2: Pre-Authorization Fraud Check
Prevent fraud before initiating payment authorization.
2.1 Order Creation
Endpoint: POST /v3/orders
Payload includes:
- Order ID
- Forter token
- Cart and pricing details
- Customer + billing/shipping info
Response:
- decision: APPROVE / DECLINE
- reason: (optional explanation)
- forterDecisionCorrelationId: Correlation ID to be passed to Phase 3 payment creation
Or, in case Forter recommends 3DS the response will include:
- Managed order token
- forterDecisionCorrelationId: Correlation ID to be passed to Phase 3 payment creation
2.2 Decision Logic
- APPROVE → proceed to payment
- DECLINE → reject transaction
- Managed Order Token → Execute 3DS
Phase 3: Payment Processing via Orchestration
Execute payments through Forter's unified orchestration layer with 3DS and routing support.
Every POST request must include a unique Idempotency-Key header, for example a UUID. If a request times out, retry it with the same key: Forter returns the original result instead of charging the customer twice. See Idempotency.
3.1 Create Payment
Endpoint: POST /api/payments
Use the same orderId you sent in Phase 2 to link the payment to the prior fraud assessment.
The forterDecisionCorrelationId field is required for Merchant Managed integrations. It links the payment to the pre-authorization fraud decision from Phase 2. Requests without it are rejected with 400.
If the Phase 2 response included a managed order token, you must pass it as managedOrderToken in the Create Payment request, after the customer has completed 3DS.
Request fields:
- orderId: the order ID you sent to Forter in Phase 2
- amount: the payment total as an integer in the currency's minor unit, for example 1099 for $10.99. See Amounts and Currencies.
- currency: uppercase ISO 4217 currency code, for example USD
- captureMethod: automatic (default) to capture right after authorization, or manual to capture later
- confirm: true to authorize immediately, or false (default) to create the payment and authorize it later with a confirm call
- forterDecisionCorrelationId: the correlation ID from the Phase 2 fraud decision response
- managedOrderToken: required if it was returned in the Phase 2 response
- paymentMethod.type: payment method type, for example token
- paymentMethod.forterTokenString: the Forter token from Phase 1
- connectionInformation.customerIP: the customer's IP address
- browserInfo.userAgent: the user agent string of the customer's browser
- cartItems: list of cart items, each with name, price (minor units), quantity, and type (tangible or non_tangible)
- shipping.deliveryMethod: delivery method, for example Standard
- shipping.deliveryType: physical, digital or hybrid
- customer.email: customer email address
- customer.firstName: customer first name
- customer.lastName: customer last name
- metadata (optional): up to 10 string key-value pairs for your own reference. See API Basics.
{
"orderId": "order-abc-123",
"amount": 1099,
"currency": "USD",
"captureMethod": "automatic",
"confirm": true,
"forterDecisionCorrelationId": "{{correlationId}}",
"managedOrderToken": "{{managedOrderToken}}",
"paymentMethod": {
"type": "token",
"forterTokenString": "{{paymentToken}}"
},
"connectionInformation": {
"customerIP": "203.0.113.10"
},
"browserInfo": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
},
"cartItems": [
{
"name": "Running shoes",
"price": 1099,
"quantity": 1,
"type": "tangible"
}
],
"shipping": {
"deliveryMethod": "Standard",
"deliveryType": "physical"
},
"customer": {
"email": "[email protected]",
"firstName": "John",
"lastName": "Smith"
}
}Key response fields:
- id: the Forter payment ID. Use it in all follow-up calls.
- orderId: the order ID associated with this payment
- status: the payment status, for example succeeded, requires_capture or failed. See Payment Lifecycle.
- amount, authorizedAmount, capturedAmount, refundedAmount: where the money stands, in minor units
- currency: ISO 4217 currency code
- captureMethod: automatic or manual
- paymentMethod: the payment method used, with masked card details
- processor: the processor that handled the payment (name) and its transactionId
- authorization: the processor's response, including the normalized processorResponseCode. See Declines and Retries.
- charges: the captures made against the payment
- createdAt, authorizedAt, capturedAt: ISO 8601 timestamps
- metadata: the metadata you sent
{
"id": "pi_v1r1a3f9c2e4b5d6478a9b0c1d2e3f4a5b6c",
"orderId": "order-abc-123",
"amount": 1099,
"capturedAmount": 1099,
"currency": "USD",
"status": "succeeded",
"captureMethod": "automatic",
"createdAt": "2026-07-14T12:34:56.789Z",
"authorizedAt": "2026-07-14T12:34:57.912Z",
"capturedAt": "2026-07-14T12:34:58.204Z",
"paymentMethod": {
"type": "card",
"card": {
"brand": "visa",
"last4": "4242",
"expirationMonth": "03",
"expirationYear": "2030"
}
},
"processor": {
"name": "braintree",
"transactionId": "k3m9x2p1"
},
"charges": [
{
"id": "charge_6f1d2c3b4a5948e7b6c5d4e3f2a1b0c9",
"amount": 1099,
"status": "succeeded",
"capturedAt": "2026-07-14T12:34:58.204Z"
}
],
"authorization": {
"authorizationCode": "123456",
"processorResponseCode": "approved"
},
"metadata": {}
}A declined payment is returned with status failed and a success HTTP status, not as an error. Always check status.
3.2 Confirm Payment
Use this step when confirm was set to false.
Endpoint: POST /api/payments/:id/confirm
No request body is needed. The response is the payment object. Its status is succeeded for automatic capture, requires_capture for manual capture, or failed if authorization was declined.
3.3 Capture Authorized Payment
Use this step when captureMethod was set to manual. amount is optional: omit it to capture the full authorized amount, or provide a smaller amount for a partial capture.
Endpoint: POST /api/payments/:id/capture
{
"amount": 1099
}Capture before authorizationExpiresAt, or extend the authorization with reauthorize. See Payment Lifecycle.
3.4 Cancel Payment
Cancel a payment that has not yet been captured.
Endpoint: POST /api/payments/:id/cancel
{
"reason": "requested_by_customer"
}Phase 4: Refunds
Endpoint: POST /api/payments/:id/refunds
Refunds a captured payment. Omit amount for a full refund, or include it for a partial refund. You can issue several partial refunds against the same payment.
{
"amount": 500,
"reason": "requested_by_customer"
}Example Response
{
"id": "refund_9b8a7c6d5e4f43a2b1c0d9e8f7a6b5c4",
"amount": 500,
"currency": "USD",
"status": "pending",
"reason": "requested_by_customer",
"chargeId": "charge_6f1d2c3b4a5948e7b6c5d4e3f2a1b0c9",
"createdAt": "2026-07-15T09:12:00.000Z"
}Most processors complete refunds asynchronously, so a new refund is usually pending. You'll receive a refund_succeeded or refund_failed webhook when the processor finishes it.
Forter handles settlement for you. If a full refund is requested before the processor has settled the capture, Forter voids the sale instead and returns the refund with status voided. A partial refund of an unsettled capture is only possible on some processors. Otherwise Forter returns an error, and you can retry after settlement. See Refunds.
Retrieve a refund with GET /api/refunds/{id}, or list the refunds for a payment with GET /api/refunds?paymentId={paymentId}.
Phase 5: Automatic Retries with Predictive Payment Routing
If the selected processor declines or fails the authorization, Forter can automatically retry it with the next-best processor recommended by Predictive Payment Routing, within the same request. The response reflects the final attempt, and no merchant action is required. See Declines and Retries.
Phase 6: Webhooks
Webhooks need two registrations:
- With your processors: where the processor offers webhooks, register Forter's endpoint in its dashboard so Forter can track asynchronous outcomes.
- With Forter: register your endpoint for Payment Orchestration Update notifications to receive payment and refund updates, such as payment_captured and refund_succeeded.
See Webhooks for setup, event types, payload format and request verification.
Phase 7: Implementation Notes
- Forter's Hosted Fields must be used for PCI compliance. Merchants are never exposed to raw card data.
- A single-use Forter token expires within 24 hours at most. If the customer chooses to store the payment method, upgrade it to a multi-use token using the Forter Tokenization API.
- Every POST request requires an Idempotency-Key header. See Idempotency.
- Handle errors as described in Errors, and see API Basics for environments, authentication and request conventions.