Zentra Developer Platform

Build a card payment

A server-to-server path for teams that own their payment form. Create a charge, guide the customer through 3DS when required, and reconcile the final result. Prefer to keep card data away from your application? Use Hosted Checkout.

REST API JSON TLS 1.2+ Version 1
01

Secure access

Authenticate from your backend with a private Zentra API key.
02

Two isolated modes

Use the test route while building, then switch the URL for live traffic.
03

Ready-to-run collection

Download the Zentra Postman collection and make a request in minutes.
01

Choose an environment

Zentra keeps test traffic isolated by route. Your API key works in both modes; the URL decides whether a payment is simulated or sent for processing.

Base
Live: https://api.zentra.solutions/api/v1/payment
Test: https://api.zentra.solutions/api/v1/test/payment
02

Separate test from live

Live
POSTRequired

/api/v1/payment/create · /api/v1/payment/status — routes via assigned MID.

Test
POSTRequired

/api/v1/test/payment/create · /api/v1/test/payment/status — simulated, no merchant gateway credentials.

Start in test mode while you build. Move to live only after your status and webhook handling are ready. Live traffic uses the MID assigned to your account.

03

Sign every request

Create a secret key in Developers. Keep it on your server and send it as a bearer token or X-API-Key header.

Header
Authorization: Bearer zentra_xxxxxxxxxxxxxxxx
X-API-Key: zentra_xxxxxxxxxxxxxxxx
04

Send your first charge

Submit the customer, billing, card, and order details in one server-side request. Your merchant_transaction_id is echoed back beside Zentra's transaction_id.

Request body

first_name
stringRequired

Customer first name

last_name
stringRequired

Customer last name

email
stringRequired

Valid email address

card_number
stringRequired

Full card number (digits only)

card_expiry_month
stringRequired

Two-digit month, e.g. 01

card_expiry_year
stringRequired

Four-digit year, e.g. 2028

card_cvv
stringRequired

Card CVV/CVC

amount
stringRequired

Charge amount, e.g. 86.40

currency
stringRequired

ISO currency code, e.g. GBP

merchant_transaction_id
stringRequired

Your unique order/reference ID

line1
stringOptional

Billing address line 1

city
stringOptional

Billing city

state
stringOptional

Billing state/province

postal_code
stringOptional

Billing postal code

country
stringRequired

ISO country code, e.g. US

phone
stringOptional

Customer phone number

ip_address
stringOptional

Customer IP address

return_url
stringOptional

Redirect URL after payment completion

cURL
curl -X POST https://api.zentra.solutions/api/v1/payment/create \
  -H "Authorization: Bearer zentra_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Maya",
    "last_name": "Chen",
    "line1": "24 Merchant Square",
    "country": "GB",
    "state": "Greater London",
    "city": "London",
    "postal_code": "W2 1JQ",
    "ip_address": "203.0.113.42",
    "email": "maya.chen@northstar-demo.test",
    "phone": "+442079460321",
    "amount": "86.40",
    "currency": "GBP",
    "card_number": "4242424242424242",
    "card_expiry_month": "01",
    "card_expiry_year": "2028",
    "card_cvv": "123",
    "return_url": "https://checkout.northstar-demo.test/payments/complete",
    "merchant_transaction_id": "NORTHSTAR-2048"
  }'

Success

JSON
{
  "status": "success",
  "reason": "Payment completed",
  "merchant_transaction_id": "NORTHSTAR-2048",
  "transaction_id": "txn_znt_8Qm2Kp7Ls4Nd"
}

3DS (test only)

Use card 4000000000003220 or amount 500+. Redirect to 3ds_url, then poll test status with the same merchant_transaction_id.

cURL
curl -X POST https://api.zentra.solutions/api/v1/test/payment/create \
  -H "Authorization: Bearer zentra_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Maya",
    "last_name": "Chen",
    "line1": "24 Merchant Square",
    "country": "GB",
    "state": "Greater London",
    "city": "London",
    "postal_code": "W2 1JQ",
    "ip_address": "203.0.113.42",
    "email": "maya.chen@northstar-demo.test",
    "phone": "+442079460321",
    "amount": "200.00",
    "currency": "GBP",
    "card_number": "4000000000003220",
    "card_expiry_month": "01",
    "card_expiry_year": "2028",
    "card_cvv": "123",
    "return_url": "https://checkout.northstar-demo.test/payments/complete",
    "merchant_transaction_id": "NORTHSTAR-3DS-2051"
  }'
JSON
{
  "status": "processing",
  "3ds_url": "https://api.zentra.solutions/test-gateway/authentication/eyJpdiI6...",
  "reason": "Payment authentication required.",
  "merchant_transaction_id": "NORTHSTAR-3DS-2051",
  "transaction_id": "txn_znt_3Ds9Tx6Jv2Qa"
}

Declined

Gateway rejection. Status declined.

JSON
{
  "status": "declined",
  "reason": "Payment failed.",
  "merchant_transaction_id": "NORTHSTAR-3DS-2051",
  "transaction_id": "txn_znt_5Bk4Hn8Rw1Ce"
}

Blocked

Zentra stopped the payment before the provider (validation, limits, fraud, country, currency, missing gateway). Status blocked.

JSON
{
  "status": "blocked",
  "reason": "Daily amount limit exceeded.",
  "merchant_transaction_id": "NORTHSTAR-3DS-2051",
  "transaction_id": "txn_znt_5Bk4Hn8Rw1Ce"
}

Validation failed

JSON
{
  "status": "blocked",
  "reason": "The first name field is required.",
  "merchant_transaction_id": "NORTHSTAR-3DS-2051",
  "transaction_id": "txn_znt_5Bk4Hn8Rw1Ce"
}
05

Retrieve the final state

Look up by merchant_transaction_id or transaction_id. Use the same live/test prefix as create.

cURL
curl -X POST https://api.zentra.solutions/api/v1/payment/status \
  -H "Authorization: Bearer zentra_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "merchant_transaction_id": "NORTHSTAR-2048"
  }'
JSON
{
  "success": true,
  "data": {
    "transaction_id": "txn_znt_7Lp2Vx9Da6Mf",
    "merchant_transaction_id": "NORTHSTAR-2048",
    "status": "success",
    "amount": 86.4,
    "currency": "GBP",
    "message": "Payment completed.",
    "customer_info": {
      "phone": "+442079460321",
      "line1": "24 Merchant Square",
      "postal_code": "W2 1JQ",
      "city": "London",
      "state": "Greater London",
      "name": "Maya Chen",
      "email": "maya.chen@northstar-demo.test",
      "country": "GB"
    },
    "created_at": "2026-10-26 18:19:53 UTC",
    "processed_at": "2026-10-26 18:19:53 UTC",
    "payment_info": {
      "card_number": "4242",
      "card_expiry_month": 1,
      "card_expiry_year": 2028
    }
  }
}
JSON
{
  "success": false,
  "error": "Transaction not found."
}
06

Read validation failures

When input validation fails, the API returns status: "blocked" with one of these exact messages in reason:

  • The first name field is required.
  • The last name field is required.
  • The email must be a valid email address.
  • The card number field is required.
  • The card CVV field is required.
07

Understand card declines

When the gateway or bank rejects a payment, status is declined and reason may be one of:

  • Payment failed.
  • Insufficient funds.
  • Card expired.
  • Invalid card number.
  • CVV verification failed.

Platform-side blocks (limits, fraud, country, currency, missing gateway) use status: "blocked" instead — see payment.blocked webhooks.

08

Simulate payment outcomes

Call /api/v1/test/payment/create. Outcome is the test card only — no external processor.

4242424242424242
cardRequired

status: success — completed immediately

4000000000000002
cardRequired

status: declined — reason: Payment failed.

4000000000003220
cardRequired

status: processing + 3ds_url — complete auth, then poll status

09

Test card library

Test endpoint /api/v1/test/payment:

4242424242424242
cardRequired

Success

4000000000003220
cardRequired

3DS authentication required

4000000000000002
cardRequired

Payment failed.

4000000000009995
cardRequired

Insufficient funds.

4111111111111111
cardRequired

Invalid card number.

Any valid card + CVV 999
cardRequired

CVV verification failed.

Any valid card + past expiry
cardRequired

Card expired.

10

Reconcile every payment

merchant_transaction_id
stringRequired

Your order reference, e.g. NORTHSTAR-2048. Use it for status lookups and reconciliation.

transaction_id
stringRequired

Zentra payment reference, e.g. txn_znt_8Qm2Kp7Ls4Nd.

11

Listen for payment events

Set the URL in Developers. Signed POST on status change or admin refund/chargeback/suspicious (and reversals). HMAC-SHA256 in X-zentra-Signature, event in X-zentra-Event, exponential backoff.

payment.completed
eventRequired

Payment succeeds (status success).

payment.declined
eventRequired

Provider/gateway rejects the payment (status declined).

payment.blocked
eventRequired

Zentra blocks the payment before the provider — validation, limits, fraud, country, currency, or missing gateway (status blocked).

payment.refunded
eventRequired

A successful payment is marked as refunded.

payment.chargeback
eventRequired

A chargeback is recorded on a payment.

payment.suspicious
eventRequired

A payment is marked suspicious.

payment.refund.reversed
eventRequired

A refund is reversed (return refund).

payment.chargeback.reversed
eventRequired

A chargeback is reversed (return chargeback).

payment.suspicious.cleared
eventRequired

A suspicious flag is cleared (return suspicious).

Body: event, timestamp, data. Lifecycle fields refund_status, chargeback_status, risk_level when relevant.

JSON
{
  "event": "payment.completed",
  "timestamp": "2026-10-26T18:19:53.000Z",
  "data": {
    "transaction_id": "txn_znt_7Lp2Vx9Da6Mf",
    "merchant_transaction_id": "NORTHSTAR-2048",
    "status": "success",
    "amount": 86.4,
    "currency": "GBP",
    "message": "Payment completed.",
    "customer_info": {
      "phone": "+442079460321",
      "line1": "24 Merchant Square",
      "postal_code": "W2 1JQ",
      "city": "London",
      "state": "Greater London",
      "name": "Maya Chen",
      "email": "maya.chen@northstar-demo.test",
      "country": "GB"
    },
    "created_at": "2026-10-26 18:19:53 UTC",
    "processed_at": "2026-10-26 18:19:53 UTC",
    "payment_info": {
      "card_number": "4242",
      "card_expiry_month": 1,
      "card_expiry_year": 2028
    }
  }
}
JSON
{
  "event": "payment.blocked",
  "timestamp": "2026-10-26T18:19:53.000Z",
  "data": {
    "transaction_id": "txn_znt_5Bk4Hn8Rw1Ce",
    "merchant_transaction_id": "NORTHSTAR-2048",
    "status": "blocked",
    "amount": 86.4,
    "currency": "GBP",
    "message": "Daily amount limit exceeded.",
    "customer_info": {
      "phone": "+442079460321",
      "line1": "24 Merchant Square",
      "postal_code": "W2 1JQ",
      "city": "London",
      "state": "Greater London",
      "name": "Maya Chen",
      "email": "maya.chen@northstar-demo.test",
      "country": "GB"
    },
    "created_at": "2026-10-26 18:19:53 UTC",
    "processed_at": "2026-10-26 18:19:53 UTC",
    "payment_info": {
      "card_number": "4242",
      "card_expiry_month": 1,
      "card_expiry_year": 2028
    }
  }
}
JSON
{
  "event": "payment.refunded",
  "timestamp": "2026-10-27T09:15:00.000Z",
  "data": {
    "transaction_id": "txn_znt_7Lp2Vx9Da6Mf",
    "merchant_transaction_id": "NORTHSTAR-2048",
    "status": "success",
    "amount": 86.4,
    "currency": "GBP",
    "message": "Payment completed.",
    "refund_status": "refunded",
    "refund_reason": "Customer requested refund",
    "refund_processed_at": "2026-10-27 09:15:00 UTC",
    "customer_info": { "email": "maya.chen@northstar-demo.test", "country": "GB" },
    "created_at": "2026-10-26 18:19:53 UTC",
    "processed_at": "2026-10-26 18:19:53 UTC",
    "payment_info": {
      "card_number": "4242",
      "card_expiry_month": 1,
      "card_expiry_year": 2028
    }
  }
}