A lightweight Python wrapper for the Nuvei REST API v1.0 — authentication, payments, 3D Secure, financial operations, subscriptions, user & payment option management, all in one package.
Requires Python 3.9+
- Features · Installation · Quick Start · Service Modules
- Integration Flows · Webhook Verification · Configuration
- Error Handling · Testing & Development · Helpful Resources
- Contributing · Changelog · License
- Full API v1.0 coverage — authentication, payments, financial operations, 3D Secure, card operations, subscriptions, user & UPO management, advanced APM
- Sync and async clients — powered by
httpx - Automatic checksum calculation — SHA-256 (default) or MD5
- Webhook/DMN verification — validate
advanceResponseChecksumon incoming notifications - Type-annotated — full type hints with
py.typedmarker (PEP 561) - Minimal dependencies — only
httpx
pip install nuveiOr for development:
pip install -e ".[dev]"from nuvei import Nuvei
client = Nuvei(
merchant_id="your_merchant_id",
merchant_site_id="your_site_id",
merchant_secret_key="your_secret_key",
environment="test", # "prod", "test", "int", "qa"
)
# 1. Get a session token
session = client.get_session_token()
token = session["sessionToken"]
# 2. Open an order
order = client.open_order(amount="10.00", currency="USD")
order_token = order["sessionToken"]
# 3. Process a payment
result = client.payments.payment(
sessionToken=order_token,
amount="10.00",
currency="USD",
paymentOption={
"card": {
"cardNumber": "4111111111111111",
"cardHolderName": "John Doe",
"expirationMonth": "12",
"expirationYear": "2028",
"CVV": "217",
}
},
)
print(result["transactionId"], result["status"])import asyncio
from nuvei import AsyncNuvei
async def main():
async with AsyncNuvei(
merchant_id="your_merchant_id",
merchant_site_id="your_site_id",
merchant_secret_key="your_secret_key",
environment="test",
) as client:
session = await client.get_session_token()
print(session["sessionToken"])
asyncio.run(main())Access API endpoints through organized service namespaces:
| Service | Accessor | Endpoints |
|---|---|---|
| Authentication | client.authentication |
get_session_token |
| Orders | client.orders |
open_order, update_order, get_order_details |
| Payments | client.payments |
payment, payment_cc, payment_apm, init_payment, get_payment_status, account_capture, get_mcp_rates, get_dcc_details |
| Financial | client.financial |
settle_transaction, refund_transaction, void_transaction, payout, get_payout_status |
| 3D Secure | client.three_d_secure |
authorize3d, verify3d, dynamic3d |
| Card Operations | client.card_operations |
card_tokenization, get_card_details |
| Users | client.users |
create_user, update_user, get_user_details |
| UPOs | client.user_payment_options |
add_upo_credit_card, add_upo_credit_card_by_temp_token, add_upo_credit_card_by_token, add_upo_apm, edit_upo_cc, edit_upo_apm, get_user_upos, delete_upo, suspend_upo, enable_upo, get_merchant_payment_methods |
| Subscriptions | client.subscriptions |
create_plan, edit_plan, get_plans_list, create_subscription, edit_subscription, cancel_subscription, get_subscriptions_list, get_subscription_plans |
| Advanced APM | client.advanced_apm |
add_bank_account, enroll_account, fund_account, get_account_details, get_document_url |
The most common flow — charge a customer immediately.
from nuvei import Nuvei
client = Nuvei(
merchant_id="...", merchant_site_id="...",
merchant_secret_key="...", environment="test",
)
# Step 1: Open an order
order = client.open_order(amount="29.99", currency="USD")
# Step 2: Process the payment
result = client.payments.payment(
sessionToken=order["sessionToken"],
amount="29.99",
currency="USD",
transactionType="Sale",
paymentOption={
"card": {
"cardNumber": "4111111111111111",
"cardHolderName": "Jane Smith",
"expirationMonth": "12",
"expirationYear": "2028",
"CVV": "217",
}
},
deviceDetails={"ipAddress": "192.168.1.1"},
)
if result["status"] == "SUCCESS" and result["transactionStatus"] == "APPROVED":
print(f"Payment approved! Transaction ID: {result['transactionId']}")Authorize first, then settle (capture) later — common for e-commerce.
# Step 1: Open order
order = client.open_order(amount="100.00", currency="USD")
# Step 2: Authorize (hold funds, don't charge yet)
auth = client.payments.payment(
sessionToken=order["sessionToken"],
amount="100.00",
currency="USD",
transactionType="Auth",
paymentOption={
"card": {
"cardNumber": "4111111111111111",
"cardHolderName": "John Doe",
"expirationMonth": "12",
"expirationYear": "2028",
"CVV": "217",
}
},
)
# Step 3: Settle (capture) — can be full or partial amount
settle = client.financial.settle_transaction(
relatedTransactionId=auth["transactionId"],
amount="100.00", # or a partial amount like "50.00"
currency="USD",
authCode=auth["authCode"],
)Full 3DS flow for liability-shifted payments.
# Step 1: Open order
order = client.open_order(amount="50.00", currency="USD")
# Step 2: Init payment — check 3DS support
init = client.payments.init_payment(
sessionToken=order["sessionToken"],
amount="50.00",
currency="USD",
paymentOption={
"card": {
"cardNumber": "4000027891380961", # 3DS test card
"cardHolderName": "CL-BRW1",
"expirationMonth": "12",
"expirationYear": "2028",
"CVV": "217",
"threeD": {
"methodNotificationUrl": "https://your-site.com/3ds-notify",
},
}
},
)
# Step 3: Handle 3DS fingerprinting (client-side iframe)
# Render the threeD data from init["paymentOption"]["card"]["threeD"]
# Step 4: Authorize 3D (after challenge completion)
auth3d = client.three_d_secure.authorize3d(
sessionToken=order["sessionToken"],
amount="50.00",
currency="USD",
paymentOption={
"card": {
"threeD": {
# Include challenge result data here
}
}
},
relatedTransactionId=init["transactionId"],
)
# Step 5: Final payment with liability shift
payment = client.payments.payment(
sessionToken=order["sessionToken"],
amount="50.00",
currency="USD",
transactionType="Sale",
relatedTransactionId=auth3d["transactionId"],
paymentOption={
"card": {
"cardNumber": "4000027891380961",
"cardHolderName": "CL-BRW1",
"expirationMonth": "12",
"expirationYear": "2028",
"CVV": "217",
}
},
)Save a payment method after the first transaction, then use it for future payments.
# --- First-time payment: Customer-Initiated Transaction (CIT) ---
# Step 1: Create the user
client.users.create_user(
userTokenId="customer_12345",
countryCode="US",
firstName="Jane",
lastName="Smith",
email="jane@example.com",
)
# Step 2: Open order with userTokenId
order = client.open_order(
amount="49.99", currency="USD",
userTokenId="customer_12345",
)
# Step 3: Process first payment (card is saved automatically with userTokenId)
first_payment = client.payments.payment(
sessionToken=order["sessionToken"],
amount="49.99",
currency="USD",
transactionType="Sale",
userTokenId="customer_12345",
paymentOption={
"card": {
"cardNumber": "4111111111111111",
"cardHolderName": "Jane Smith",
"expirationMonth": "12",
"expirationYear": "2028",
"CVV": "217",
}
},
)
# Step 4: Get saved payment methods (UPOs)
upos = client.user_payment_options.get_user_upos(
userTokenId="customer_12345",
)
upo_id = upos["paymentMethods"][0]["userPaymentOptionId"]
# --- Future payment: Use saved UPO (CIT or MIT) ---
order2 = client.open_order(
amount="49.99", currency="USD",
userTokenId="customer_12345",
)
future_payment = client.payments.payment(
sessionToken=order2["sessionToken"],
amount="49.99",
currency="USD",
transactionType="Sale",
userTokenId="customer_12345",
paymentOption={"userPaymentOptionId": upo_id},
isRebilling="0", # "1" for MIT (merchant-initiated)
)Set up automatic recurring payments.
# Step 1: Create a plan
plan = client.subscriptions.create_plan(
name="Premium Monthly",
initialAmount="0.00",
recurringAmount="29.99",
currency="USD",
endAfter={"day": "0", "month": "12", "year": "0"},
startAfter={"day": "0", "month": "1", "year": "0"},
)
# Step 2: Create a subscription for the user
sub = client.subscriptions.create_subscription(
userTokenId="customer_12345",
planId=plan["planId"],
userPaymentOptionId=upo_id,
initialAmount="0.00",
recurringAmount="29.99",
currency="USD",
endAfter={"day": "0", "month": "12", "year": "0"},
)
# Step 3: List active subscriptions
subs = client.subscriptions.get_subscriptions_list(
userTokenId="customer_12345",
subscriptionStatus="ACTIVE",
)
# Step 4: Cancel when needed
client.subscriptions.cancel_subscription(
subscriptionId=sub["subscriptionId"],
)# Full refund
refund = client.financial.refund_transaction(
relatedTransactionId="original_txn_id",
amount="49.99",
currency="USD",
clientUniqueId="refund-001",
authCode="original_auth_code",
)
# Partial refund
partial_refund = client.financial.refund_transaction(
relatedTransactionId="original_txn_id",
amount="10.00", # partial amount
currency="USD",
clientUniqueId="refund-002",
authCode="original_auth_code",
)Cancel a transaction before settlement.
void = client.financial.void_transaction(
relatedTransactionId="original_txn_id",
amount="49.99",
currency="USD",
authCode="original_auth_code",
)Send money to a payment method (credit/disbursement).
payout = client.financial.payout(
userTokenId="customer_12345",
amount="100.00",
currency="USD",
userPaymentOption={"userPaymentOptionId": upo_id},
comment="Withdrawal payout",
)
# Check payout status
status = client.financial.get_payout_status(
clientRequestId=payout["clientRequestId"],
)Nuvei sends Direct Merchant Notifications (DMN) to your server after transaction events. Always verify the checksum.
from nuvei import verify_webhook
# In your webhook handler (Flask, FastAPI, Django, etc.)
def handle_nuvei_webhook(params: dict):
is_valid = verify_webhook(
params,
merchant_secret_key="your_secret_key",
raise_on_failure=False, # or True to raise ChecksumError
)
if is_valid:
txn_id = params.get("PPP_TransactionID")
status = params.get("Status")
# Process the notification...For custom DMN types with different field orderings:
from nuvei import verify_webhook_generic
verify_webhook_generic(
params,
merchant_secret_key="your_secret_key",
checksum_fields=["fieldA", "fieldB", "fieldC"],
checksum_param="advanceResponseChecksum",
secret_position="prefix", # or "suffix"
)# Default is SHA-256; switch to MD5 if your account requires it
client = Nuvei(..., algorithm="md5")| Environment | Base URL |
|---|---|
prod |
https://secure.safecharge.com |
test |
https://ppp-test.nuvei.com |
int |
https://ppp-test.nuvei.com |
qa |
https://apmtest.gate2shop.com |
# Auto-close the HTTP client
with Nuvei(...) as client:
session = client.get_session_token()The SDK raises specific exceptions for different failure modes:
from nuvei import APIError, AuthenticationError, TransportError, ChecksumError
try:
result = client.payments.payment(...)
except AuthenticationError as e:
# Session token or credential issues
print(f"Auth failed: {e.reason}")
except APIError as e:
# Nuvei API returned an error
print(f"API error {e.err_code}: {e.reason}")
print(e.response_body) # full response dict
except TransportError as e:
# Network / HTTP-level errors
print(f"Network error: {e}")Every API method returns the full response dict from Nuvei. Check these fields:
| Field | Description |
|---|---|
status |
"SUCCESS" or "ERROR" — indicates if the request was processed |
errCode |
0 for success, non-zero for errors |
reason |
Human-readable error description |
transactionStatus |
"APPROVED", "DECLINED", "PENDING", "ERROR" — actual transaction result |
transactionId |
Nuvei's unique transaction identifier |
authCode |
Authorization code from the issuer |
gwErrorCode |
Gateway-specific error code |
gwErrorReason |
Gateway-specific error description |
Important: A
status: "SUCCESS"means the request was processed — it does NOT mean the transaction was approved. Always checktransactionStatusfor the actual result.
For more details, see: Nuvei Response Handling Guide
pip install -e ".[dev]"
python -m pytest tests/ -vUse these test card numbers in the test environment:
| Card Number | Brand | Behavior |
|---|---|---|
4111111111111111 |
Visa | Approved |
5111111111111118 |
Mastercard | Approved |
4000027891380961 |
Visa | 3DS Challenge |
4000020951595032 |
Visa | 3DS Frictionless |
4000023104662535 |
Visa | Declined |
- Expiry date: Any future date (e.g.
12/2028) - CVV: Any 3 digits (e.g.
217)
For the full list of testing cards, see: Nuvei Testing Cards
Nuvei provides a Postman collection for testing API calls interactively:
- Import the Nuvei API collection into Postman
- Set environment variables:
merchantId,merchantSiteId,merchantSecretKey - Use the collection to test individual endpoints and verify responses
For details, see: Testing APIs with Postman
| Resource | Link |
|---|---|
| Nuvei API v1.0 Reference | Main API Docs |
| Advanced API Reference | Advanced API Docs |
| Response Handling | Response Handling Guide |
| Webhooks (DMN) | Webhook Documentation |
| Testing Cards | Testing Cards Reference |
| Testing with Postman | Postman Guide |
| 3D Secure | 3DS Documentation |
| Financial Operations | Financial Ops Guide |
| Subscription/Rebilling | Subscription Docs |
| Authentication | Auth Documentation |
| Checksum Tool | Online Checksum Calculator |
Contributions are welcome! If you find a bug, have a feature request, or want to improve the SDK:
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Commit your changes and add tests
- Open a pull request
For bugs or questions, open an issue.
See CHANGELOG.md for a full list of changes in each release.
MIT — see LICENSE for details.
Made with Python & ❤️ by KK Jangid