Embedded card widget
Accept Visa and Mastercard payments in a widget embedded on your own page with payment_method card, without redirecting the customer.
With payment_method: "card", the customer enters the card on your page, in a widget provided by Tranzak and powered by Stripe. There is no redirect, and card data never passes through your server or ours.
Access
| Mode | Availability |
|---|---|
Test key (tk_test_) |
Works immediately. Test freely, widget included. |
Live key (tk_live_) |
Requires approval. Request it from the dashboard: Payment methods → Request access. Until it is approved, live requests answer 403 payment_method_not_approved. |
Minimum amount
Stripe refuses card payments below 0.50 USD (about 65 HTG). Tranzak checks this before calling Stripe: below the minimum, the API answers 400 amount_too_low with the exact minimum in message, and no transaction is created.
Read the current minimum in card_minimum of the exchange rate endpoint to disable your pay button before the customer clicks.
1. Create the payment on your server
curl https://api.tranzak.co/api/gateway/v1/payments \
-H "X-Api-Key: $TRANZAK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 500,
"currency": "HTG",
"payment_method": "card",
"customer_name": "Jean Dupont",
"customer_email": "[email protected]"
}'
const res = await fetch('https://api.tranzak.co/api/gateway/v1/payments', {
method: 'POST',
headers: { 'X-Api-Key': process.env.TRANZAK_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({
amount: 500,
currency: 'HTG',
payment_method: 'card',
customer_name: 'Jean Dupont',
customer_email: '[email protected]',
}),
});
const payment = await res.json();
// Send payment.client_secret and payment.publishable_key to your page
import os, requests
payment = requests.post(
"https://api.tranzak.co/api/gateway/v1/payments",
headers={"X-Api-Key": os.environ["TRANZAK_API_KEY"]},
json={
"amount": 500,
"currency": "HTG",
"payment_method": "card",
"customer_name": "Jean Dupont",
"customer_email": "[email protected]",
},
).json()
# Send payment["client_secret"] and payment["publishable_key"] to your page
The response has no payment_url. It returns what the widget needs:
{
"success": true,
"transaction_id": "17843268616389",
"amount": "500.00",
"currency": "HTG",
"status": "requires_payment_method",
"payment_intent_id": "pi_3UJIANGPt6aUvL4Q…",
"client_secret": "pi_3UJIANGPt6aUvL4Q…_secret_…",
"publishable_key": "pk_test_…"
}
HTG amounts are converted to USD for Stripe at the rate returned by the exchange rate endpoint.
2. Show the widget on your page
<div id="tranzak-card-element"></div>
<button id="pay-btn">Pay</button>
<script src="https://api.tranzak.co/js/tranzak-card.js"></script>
<script>
TranzakCard.mount({
containerId: 'tranzak-card-element',
clientSecret: payment.client_secret,
publishableKey: payment.publishable_key,
});
document.getElementById('pay-btn').addEventListener('click', function () {
TranzakCard.confirm({
onSuccess: function (paymentIntent) { /* update the screen only */ },
onError: function (error) { /* card declined, show error.message */ },
});
});
</script>
Warning
onSuccessis an immediate callback from Stripe, not proof of payment. The source of truth is thepayment.successwebhook orGET /payments/{transaction_id}.
Errors
Card declines are returned with Stripe's customer-safe message. Other provider problems return a generic "temporarily unavailable" message. Show the message to the customer, and let them try another card.
Test cards
With a test key the widget runs in real Stripe test mode. See Sandbox and test mode.