status=20, direct the cardholder to challenge_url, then confirm the final payment result through an order query or a verified webhook notification.status=20 and challenge_url.| Item | Requirement |
|---|---|
| API base URL | Use the environment URL provided by TrustPay, referred to below as TRUSTPAY_API_BASE |
| HTTP method | POST |
| Request and response format | UTF-8 JSON |
| Headers | Content-Type: application/json and X-Api-Key: YOUR_API_KEY |
| Signature field | sign in the request JSON |
| Amount unit | Major currency units; order_amount: 10 means USD 10, not 10 cents |
| Merchant identity | Determined by the API key; no additional merchant ID is required in the request bodies below |
sign field.null or an empty string. Include numeric 0 and Boolean false.key1=value1&key2=value2. Do not URL-encode the values.&secret=YOUR_SECRET.10.00 becomes 10 in the signature string. Include nonempty fields such as payment_success_url and payment_failed_url. The request examples use scalar fields only; you do not need to add a nested browser object for this integration.order_no=MCH-3DS-20261029-001&secret=YOUR_SECRET{
"order_no": "MCH-3DS-20261029-001",
"order_amount": 10,
"currency": "USD",
"notify_url": "https://merchant.example.com/webhooks/trustpay",
"payment_success_url": "https://merchant.example.com/payment/result?order_no=MCH-3DS-20261029-001",
"payment_failed_url": "https://merchant.example.com/payment/result?order_no=MCH-3DS-20261029-001",
"card_number": "TEST_CARD_NUMBER",
"card_expiry": "2028-07",
"card_cvv": "TEST_CVV",
"card_holder_first_name": "Jane",
"card_holder_last_name": "Doe",
"card_holder_email": "jane@example.com",
"card_holder_phone": "14155550100",
"billing_address_street": "123 Test Street",
"billing_city": "San Francisco",
"billing_state": "CA",
"billing_postal_code": "94105",
"billing_country": "US",
"client_ip": "PAYER_PUBLIC_IP",
"sign": "CALCULATED_SIGNATURE"
}client_ip with the cardholder's actual public IP address, and then calculate the signature. The placeholder values cannot be submitted as a valid payment.| Field | Requirement and description |
|---|---|
order_no | Required. Your merchant order reference. Keep the same reference throughout the payment flow |
order_amount, currency | Required. This C21 integration currently uses USD |
card_number, card_cvv | Required. Card number and a three- or four-digit CVV |
card_expiry | Required. TrustPay JSON uses YYYY-MM, for example 2028-07 |
card_holder_first_name, card_holder_last_name | Required. The cardholder's first and last names |
| Cardholder email, phone, and billing address fields | Provide complete details for C21. Use digits only for phone numbers and a two-letter country code. Use a valid two-letter state or province code for US and Canadian addresses |
client_ip | Required when customer IP collection is enabled for the merchant. Supply the cardholder's actual IP address |
notify_url | Optional, recommended. Your backend endpoint for payment result notifications |
payment_success_url, payment_failed_url | Optional HTTPS URLs. The verification page can offer a return to the relevant merchant result page. Query the order through your backend after the customer returns |
sign | Required. Generate it using Section 2 |
browser, three_ds_session_id, or attempt_id. TrustPay collects browser information on the verification page when needed.payment-request.json, then submit it from your backend:code describes the API business result. data.status describes the order status. Neither HTTP 200 nor code=880001 alone proves that a payment succeeded.{
"code": 880001,
"message": "success",
"data": {
"order_no": "MCH-3DS-20261029-001",
"platform_order_no": "TRUSTPAY_ORDER_ID",
"currency": "USD",
"order_amount": 10,
"paid_amount": 0,
"fee": 0.5,
"reserve": 1,
"status": 20,
"challenge_url": "https://checkout.example.com/3ds/SESSION_ACCESS_TOKEN"
}
}platform_order_no is the TrustPay order ID.20, named 3ds_pending, means the payment requires cardholder action. The URL may begin with device data collection or display a bank challenge immediately. Certain recovery scenarios may ask the cardholder to re-enter the CVV. Status 20 is not a payment failure and must not trigger a new payment submission.{
"code": 880001,
"message": "success",
"data": {
"order_no": "MCH-3DS-20261029-001",
"platform_order_no": "TRUSTPAY_ORDER_ID",
"currency": "USD",
"order_amount": 10,
"paid_amount": 10,
"fee": 0.5,
"reserve": 1,
"status": 5
}
}| status | Meaning | Merchant action |
|---|---|---|
1 | Pending payment or processing | Show a pending state and continue querying. Do not fulfill the order or submit another charge based on this status |
20 | Waiting for cardholder action for 3DS | Open challenge_url in the browser and keep the original order |
5 | Paid; funds awaiting release | Treat the payment as successful. Fund availability follows the applicable settlement rules |
6 | Paid; funds released | Treat the payment as successful |
17 | Settled | The order has reached settlement. Do not repeat fulfillment or other completed business actions |
3 | Payment failed | Display the failure reason. A new payment requires an explicit customer action |
4 | Order timed out | Handle the timeout without automatically submitting another charge |
18 | Accounting review pending | Keep the result unconfirmed and contact TrustPay. Do not treat it as successful or automatically charge again |
status=2 as your sole success criterion for this C21 pay-in integration.challenge_url is the complete URL of a TrustPay hosted verification page. Use the URL returned by the API without constructing it yourself or parsing its token. Open it in the cardholder's browser; do not call it as a backend payment API. A full-page browser redirect is recommended for compatibility with bank authentication screens.showMessage and refreshOrderFromMerchantBackend in your application. The input is the TrustPay response forwarded by your backend.| URL | Recipient | Purpose |
|---|---|---|
challenge_url | Cardholder's browser opens a TrustPay page | Perform the required device collection or authentication |
payment_success_url, payment_failed_url | Merchant frontend | Return to your result page, which then queries your backend |
notify_url | Merchant backend | Receive payment result webhook notifications |
C21 returnUrl | TrustPay | Receive the bank authentication return and continue payment completion |
returnUrl endpoint or handle bank JWTs, stepUpUrl, DeviceData, or Authenticate3DSPayment.{
"order_no": "MCH-3DS-20261029-001",
"sign": "CALCULATED_SIGNATURE"
}{
"code": 880001,
"message": "success",
"data": {
"order_no": "MCH-3DS-20261029-001",
"platform_order_no": "TRUSTPAY_ORDER_ID",
"type_id": 0,
"merchant_id": 10001,
"currency": "USD",
"order_amount": 10,
"paid_amount": 0,
"status": 20,
"challenge_url": "https://checkout.example.com/3ds/CURRENT_ACCESS_TOKEN"
}
}5 and 6 according to their successful payment meanings, and continue waiting for 1. During an interactive flow, consider querying every few seconds, then reducing the frequency. Stop polling completed orders and comply with the rate limits agreed for your environment.notify_url. A separate 3DS notification endpoint is not required. Payment notifications are sent as POST JSON. Example successful payment notification:{
"type": 0,
"merchant_id": 10001,
"order_no": "MCH-3DS-20261029-001",
"order_amount": 10,
"paid_amount": 10,
"balance_amount": 9.5,
"fee": 0.5,
"status": 5,
"reason": "payment received",
"pay_time": "2026-10-29T04:00:00Z",
"sign": "CALCULATED_NOTIFICATION_SIGNATURE"
}balance_amount follows the existing payment notification definition; it does not mean all funds are immediately available.status=20 and challenge_url from the payment response or order query. Do not wait for a webhook to begin verification. If a notification is not received, query the original order to confirm the result.| Situation | Required handling |
|---|---|
| The customer closes the verification page or returns to your site | Query the original order. If it still returns 20 with a URL, offer a “Continue verification” button |
| An old link expires | Query the original order from your backend and use the currently returned link. A fresh access link does not guarantee that expired authentication material can be recovered |
| The order is processing with no verification link | Keep showing a pending state and continue querying. Do not construct a URL or force a new 3DS flow |
| HTTP timeout, 403, 502, or a channel error | Keep the original order reference and verify its result. A network error alone does not prove that no charge occurred |
| Status 20 is returned without a link | Query the original order. Contact TrustPay if this persists; do not automatically charge again |
| Payment remains unconfirmed after authentication | Continue querying. Completing a verification code or bank challenge does not itself prove payment success |